diff --git a/localstack-core/localstack/services/events/event_rule_engine.py b/localstack-core/localstack/services/events/event_rule_engine.py index 157bd6e95c367..a1af9a9cdb339 100644 --- a/localstack-core/localstack/services/events/event_rule_engine.py +++ b/localstack-core/localstack/services/events/event_rule_engine.py @@ -43,7 +43,7 @@ def _evaluate_nested_event_pattern_on_dict(self, event_pattern, payload: dict) - # TODO: maybe save/cache the flattened/expanded pattern? flat_pattern_conditions = self.flatten_pattern(event_pattern) - flat_payloads = self.flatten_payload(payload) + flat_payloads = self.flatten_payload(payload, flat_pattern_conditions) return any( all( @@ -51,10 +51,10 @@ def _evaluate_nested_event_pattern_on_dict(self, event_pattern, payload: dict) - self._evaluate_condition( flat_payload.get(key), condition, field_exists=key in flat_payload ) - for condition in values + for condition in conditions for flat_payload in flat_payloads ) - for key, values in flat_pattern.items() + for key, conditions in flat_pattern.items() ) for flat_pattern in flat_pattern_conditions ) @@ -147,7 +147,7 @@ def _evaluate_cidr(condition: str, value: str) -> bool: @staticmethod def _evaluate_wildcard(condition: str, value: str) -> bool: - return re.match(re.escape(condition).replace("\\*", ".+") + "$", value) + return bool(re.match(re.escape(condition).replace("\\*", ".+") + "$", value)) @staticmethod def _evaluate_numeric_condition(conditions: list, value: t.Any) -> bool: @@ -237,18 +237,24 @@ def _traverse_event_pattern(obj, array=None, parent_key=None) -> list: return _traverse_event_pattern(nested_dict) @staticmethod - def flatten_payload(nested_dict: dict) -> list[dict]: + def flatten_payload(payload: dict, patterns: list[dict]) -> list[dict]: """ Takes a dictionary as input and will output the dictionary on a single level. The dictionary can have lists containing other dictionaries, and one root level entry will be created for every - item in a list. + item in a list if it corresponds to the entries of the patterns. Input: + payload: `{"field1": { "field2: [ {"field3: "val1", "field4": "val2"}, {"field3: "val3", "field4": "val4"}, } ]}` + patterns: + `[ + "field1.field2.field3": , + "field1.field2.field4": , + ]` Output: `[ { @@ -260,16 +266,25 @@ def flatten_payload(nested_dict: dict) -> list[dict]: "field1.field2.field4": "val4" }, ]` - :param nested_dict: a (nested) dictionary + :param payload: a (nested) dictionary, the event payload + :param patterns: the flattened patterns from the EventPattern (see flatten_pattern) :return: flatten_dict: a dictionary with no nested dict inside, flattened to a single level """ + patterns_keys = {key for keys in patterns for key in keys} + + def _is_key_in_patterns(key: str) -> bool: + return key is None or any(pattern_key.startswith(key) for pattern_key in patterns_keys) def _traverse(_object: dict, array=None, parent_key=None) -> list: if isinstance(_object, dict): for key, values in _object.items(): - # We update the parent key do that {"key1": {"key2": ""}} becomes "key1.key2" + # We update the parent key so that {"key1": {"key2": ""}} becomes "key1.key2" _parent_key = f"{parent_key}.{key}" if parent_key else key - array = _traverse(values, array, _parent_key) + + # we make sure that we are building only the relevant parts of the payload related to the pattern + # the payload could be very complex, and the pattern only applies to part of it + if _is_key_in_patterns(_parent_key): + array = _traverse(values, array, _parent_key) elif isinstance(_object, list): if not _object: @@ -279,7 +294,7 @@ def _traverse(_object: dict, array=None, parent_key=None) -> list: array = [{**item, parent_key: _object} for item in array] return array - return _traverse(nested_dict, array=[{}], parent_key=None) + return _traverse(payload, array=[{}], parent_key=None) class EventPatternCompiler: diff --git a/tests/aws/services/events/test_events_patterns.py b/tests/aws/services/events/test_events_patterns.py index ff4c079970b69..a8af3d5cc1a8b 100644 --- a/tests/aws/services/events/test_events_patterns.py +++ b/tests/aws/services/events/test_events_patterns.py @@ -11,6 +11,7 @@ from localstack.testing.pytest import markers from localstack.utils.common import short_uid +from localstack.utils.files import load_file from tests.aws.services.events.helper_functions import ( is_old_provider, sqs_collect_messages, @@ -22,6 +23,7 @@ REQUEST_TEMPLATE_DIR, "complex_multi_key_event_pattern.json" ) COMPLEX_MULTI_KEY_EVENT = os.path.join(REQUEST_TEMPLATE_DIR, "complex_multi_key_event.json") +TEST_PAYLOAD_DIR = os.path.join(THIS_FOLDER, "test_payloads") def load_request_templates(directory_path: str) -> List[Tuple[dict, str]]: @@ -262,6 +264,27 @@ def test_invalid_event_payload(self, aws_client, snapshot): ) snapshot.match("plain-string-payload-exc", e.value.response) + @markers.aws.validated + def test_event_with_large_and_complex_payload(self, aws_client, snapshot): + event_file_path = os.path.join(TEST_PAYLOAD_DIR, "large_complex_payload.json") + event = load_file(event_file_path) + + simple_pattern = {"detail-type": ["cmd.documents.generate"]} + response = aws_client.events.test_event_pattern( + Event=event, + EventPattern=json.dumps(simple_pattern), + ) + snapshot.match("complex-event-simple-pattern", response) + + complex_pattern = { + "detail": {"payload.nested.another-level.deep": {"inside-list": [{"prefix": "q-test"}]}} + } + response = aws_client.events.test_event_pattern( + Event=event, + EventPattern=json.dumps(complex_pattern), + ) + snapshot.match("complex-event-complex-pattern", response) + class TestRuleWithPattern: @markers.aws.validated diff --git a/tests/aws/services/events/test_events_patterns.snapshot.json b/tests/aws/services/events/test_events_patterns.snapshot.json index b3107a1fe986c..3dbc5cd4f1301 100644 --- a/tests/aws/services/events/test_events_patterns.snapshot.json +++ b/tests/aws/services/events/test_events_patterns.snapshot.json @@ -1296,5 +1296,24 @@ "exception_type": "" } } + }, + "tests/aws/services/events/test_events_patterns.py::TestEventPattern::test_event_with_large_and_complex_payload": { + "recorded-date": "17-03-2025, 10:58:02", + "recorded-content": { + "complex-event-simple-pattern": { + "Result": true, + "ResponseMetadata": { + "HTTPHeaders": {}, + "HTTPStatusCode": 200 + } + }, + "complex-event-complex-pattern": { + "Result": true, + "ResponseMetadata": { + "HTTPHeaders": {}, + "HTTPStatusCode": 200 + } + } + } } } diff --git a/tests/aws/services/events/test_events_patterns.validation.json b/tests/aws/services/events/test_events_patterns.validation.json index f32603a50e398..e4d69240f1b7a 100644 --- a/tests/aws/services/events/test_events_patterns.validation.json +++ b/tests/aws/services/events/test_events_patterns.validation.json @@ -401,6 +401,9 @@ "tests/aws/services/events/test_events_patterns.py::TestEventPattern::test_event_pattern_with_multi_key": { "last_validated_date": "2024-07-11T13:55:38+00:00" }, + "tests/aws/services/events/test_events_patterns.py::TestEventPattern::test_event_with_large_and_complex_payload": { + "last_validated_date": "2025-03-17T10:58:02+00:00" + }, "tests/aws/services/events/test_events_patterns.py::TestEventPattern::test_invalid_event_payload": { "last_validated_date": "2024-12-05T17:44:17+00:00" }, diff --git a/tests/aws/services/events/test_payloads/large_complex_payload.json b/tests/aws/services/events/test_payloads/large_complex_payload.json new file mode 100644 index 0000000000000..d01727f12c2c9 --- /dev/null +++ b/tests/aws/services/events/test_payloads/large_complex_payload.json @@ -0,0 +1,874 @@ +{ + "id": "1", + "source": "soft1", + "detail-type": "cmd.documents.generate", + "account": "123456789012", + "region": "us-east-2", + "time": "2022-07-13T13:48:01Z", + "detail": { + "sourceHostname": "lambda.amazonaws.com", + "sourceMessagingLib": "w", + "correlationUuid": "a26f70c2-e071-459f-8b87-81fdfb43e28a", + "createdAt": "2025-03-14T17:05:46.019Z", + "retryCount": 0, + "metadata": {}, + "payload": { + "WElTQLlSVUBpx": "zCUYxaqSGUXLtCVyHiAcRJxKnBcLeac", + "URXrhXqFQULAGIVx": 6, + "AWFqITBBeoWQ": "TopVogywzrBtZWTMWadzyUmTAOfcPxwwuJbc", + "NwVWQPgFRzeENvXIblm": "NQmVRJbvVDtHoVuFaOFvZEhM", + "RVjgwOLpVhEPhsUdGCmc": "DfsbMyKZUKBvQvidnzXPGGom", + "nested": { + "MhuRrcNygnJ": { + "MsMzulBhOI": "TKBLUCBZ", + "uYOQyOyWlCREF": "JeCNesuWhslgGYnZDjmNOBzqGEJicBqgvFzJcGnfNhajYSPQMMJsMzqNbWhNxCHJfzKuqKuvVCprLFVQgCsYIihQVvbpLiLLmoFeXiy", + "yOIbDKLerwwRVJKnjpi": 14, + "zyHteNLbKlOttm": [ + { + "Yf": "W", + "AOpS": "iJvXlgsrunicxdTuukghMcw", + "tnFMYzoWwB": "mBGLRKGfSaOKfiCIa" + } + ], + "YCxEXubXBBOROVD": { + "bjQQvYoyFzYiDGvon": [ + { + "yaXLKTjG": 191, + "UzhK": "VrkanWpo", + "XgOvBdEVfr": 3289, + "xkZq": "PpQ", + "Go": 944, + "Tb": 854, + "qNTcP": 132, + "Dbb": 3.97, + "WEA": 38, + "OTF": 2117, + "WMcSFly": 50.6, + "ROzkCJoGm": 92.67, + "eSePorxJI": 8.164598354536087, + "knoJyMOoK": 1.894621779845863, + "nKsgnqAZs": 4.423379701209955, + "hquYzxZ": 1.173164884858382, + "JTIfuzg": 65.79, + "TlxyyuZ": 60.35, + "cZhilKYDflAzFzOc": "yeCuYBmA", + "ZvuzDFjGtdclKcJEVMZP": "tp", + "BfUnZuOfCcuRMj": "NLehVjkCzjmZGRHsOjKZEb" + } + ] + }, + "gwooISnKeGTLdFimWkju": null + }, + "hnWBTAzubJWQmLDY": { + "ufulSIPsMu": "fjbMKRRA", + "fAsGuGrUajGhL": "keuqGQQqJunZDqXlxaLYXbMeZclCPQMqecurApAcDJso", + "BOUfucwDQWNHgb": "iLHbpUokCDovAhNvOOmswXLRMYSOtOIKtGNTCMlmeK", + "aHmXVKiuoQNWeWavLgO": 29, + "LCjOZFlCoHbMkAGeKl": 0, + "OkcbFmLlXzkooW": [ + { + "Zk": "dYPSbrHlicABJxQEUmPGHA", + "iuZV": "ixXPRFPqvkdtPGTaWrRYnNkJARfKnTGmUHNGHoGIfSM", + "WyVGwfcAXa": "hBXltKbzeAWLunuJAg" + } + ], + "vfxjgRVADEkWhxP": { + "vmNxIhDGBdCJvIFPRi": [ + { + "mCvvonTb": 7942264, + "zKzk": 9, + "xEAthobZTu": 8, + "eKgMzIe": 8, + "XdUQy": "pdJzICPuMYOvBUNlootMHYXYhcKJt", + "zBKcgiQUd": "sAHYUVTjbAWdgFQEmrRuZsGichOjV" + }, + { + "MrElexnI": 7652102, + "Ehbv": 1, + "HIbcTxEaUX": 5, + "WmRycFY": 4, + "JFLMQ": "vJDgJauwsABMZFbUTffrioCpBGmse", + "jyMEFezhT": "FfJJeYrLQnDGCrMCnXxJwGEJMlJfo" + }, + { + "cHncKhRL": 1693855, + "muAr": 2, + "SNbOLmbeZu": 7, + "mULkTxE": 3, + "gKycu": "BIGJnSim", + "SkxMGyvYx": "havqqzSM" + }, + { + "GyZFLuoQ": 2976017, + "SqCm": 51, + "hSZoojwlFH": 2, + "CSyLRCI": 1, + "KGpgu": "jHmDzLQEVkKrcUt", + "XFMSAIUoj": "iwhbcYcBflLBVsF" + }, + { + "BIHvwrHi": 1043893, + "cWnu": 2, + "zONwuXyZPu": 3, + "YgnMYTl": 7, + "GqjQa": "vwiRRNiJ", + "pgPlJFhcm": "cDHRlLYL" + }, + { + "SuIixzIv": 9249481, + "jTgZ": 6, + "vjgbsBqnoQ": 5, + "MgSMFQm": 6, + "gIARZ": "eMXqInvJBgWbTHgxgOPDioCcoDCj", + "dArwvMcuW": "cJQpdjdlmFlArjSBRaTxMpjyRCWH" + }, + { + "UxaDeEaF": 2538086, + "Qzqe": 3, + "EcJKQAPywI": 4, + "FswYsld": 4, + "XhnBj": "WkKYsqRwxIQNtVOByOMaUCBGUmykb", + "Onfbkbwca": "SpZlMUtNfnBXwEnzytLqlvYcdESPp" + }, + { + "wqZfLRXV": 6866658, + "ppIy": 7, + "omfEsDSBpm": 9, + "neVloPA": 6, + "kVSAt": "WztMWoqBsQFfwo", + "WubGMvWiT": "QIsSzDmeNlprfk" + }, + { + "LzwRmmgZ": 3224814, + "YJlg": 2, + "ocNTsgJsFA": 3, + "SPqPpJu": 4, + "nWTWz": "QaUpdhcrklslGrNjKxcJVmNsndepR", + "hPPcNtPlm": "MnvHHzNYPENYhSUFDoLcrwgbpjyaF" + }, + { + "jjhPZjTv": 3373968, + "mmrI": 8, + "YkJCEwyLdG": 2, + "NRhwMJn": 5, + "lpkaO": "QeiODlPPFqFUqfoulSLrCucINWhPf", + "ZzoWtjchC": "cfdtheSrvRJxqvZSKFqcFNKjjWiuF" + }, + { + "XwGDqdRU": 8445297, + "uJfU": 7, + "yzKOqetYwV": 2, + "FwkZEQG": 3, + "XesxG": "yiXveXvEgdnwVkoISGNejILgpAzjZZMoSygG", + "cuoUeiPgY": "xyppRzMXiHmuUVsmkWjYibiHFTESETGAApWO" + }, + { + "hptqabaG": 5953056, + "hJPc": 8, + "zoltzLwnRq": 8, + "mqKONTM": 8, + "FIOoG": "XpkeOWtM", + "EZjrNXtDs": "FRUoivil" + }, + { + "MMPxfvpd": 2700237, + "WhsD": 6, + "VnNsPWOgBE": 2, + "RQuokGn": 6, + "fdeLB": "FulxrCKUMkvqHxNLSoOvDbLeDpXQn", + "tvSdPHpYe": "kOJcPRRSMXGRMytCegLFGqFjGTTqh" + }, + { + "wLPifMoa": 8803711, + "xnpd": 3, + "HNqCRsMwdz": 8, + "wTHcwQi": 5, + "pWXDZ": "xoUqqOgidcrCyWSKOUqQKTGoBCYaQBdcilIS", + "juUIJCKTw": "frJOdSOmOHzlPsHffGlrwnlaQYNhSheVVvuc" + }, + { + "QnRuUKZS": 7742212, + "fjUv": 9, + "NOIULzKDFU": 5, + "xrRHTyw": 2, + "IjUms": "evEFIbPqZojTcy", + "QxzjvmCku": "VgXgHRNAayjRFE" + }, + { + "xdkiUPxT": 6876317, + "JvvB": 9, + "IwvPwGCzAT": 6, + "zvjOzqE": 4, + "KRlJS": "BJMStNIALLJjRkxnjFoSXxDpBpBBl", + "GnDsNdjsv": "fDJndULJzYANHpFTLdMQtBdHcGbje" + }, + { + "aHQIfnrJ": 6313562, + "vVur": 4, + "soPcZyqqSm": 6, + "tlpFZPT": 6, + "HYlGB": "CvKTRdKSaqkLzbTCzCMSxBASBTCF", + "TZkTcZXxp": "SuEHDdBaECVBoPUwzgPCKurmCBDl" + }, + { + "wUHQFWHE": 8259408, + "VzUD": 7, + "clhmPXUief": 2, + "rysfyAl": 4, + "hTwJh": "swkgJseZNdKwXocQxeuuDiAhAkAyStXkRSgD", + "mdhBfqDrX": "MejSWHcnIAMSWXqffbmCWTSXpRbmyBlTeTKs" + }, + { + "BcLOBQRV": 2384915, + "xLJP": 5, + "yaIXYcuwCD": 2, + "ukVDPQv": 8, + "eMQSO": "uZyMjsmcJRwIrxlWhWlQuJznaunk", + "LhXRomjux": "zANDenVmhGNFJKeARKkXEEBRkoMM" + }, + { + "UACXwlbS": 4593772, + "YjLr": 5, + "beFaYBKHiA": 7, + "gkdxrVL": 8, + "ojfFY": "dnYQdCeMnqqxZN", + "DRNVjRfjH": "fhRNwOUrFXLDAV" + } + ] + }, + "JKrdOYIQUutPaKIMHiFf": null + }, + "iYPjyGjAKeIwmIKPwzAzgvsVSASYns": { + "HyRwEDlNhK": "INYowiqg", + "ixDNOnyHIPhQt": "pCYJORoZMMqjDPzHTIGzslDrBFWwSUuaRRdywVkuSuTFHwjHKAOzYDMVKvXhVEGqVRIUJllDWChdjfGRRDxwQZikiRQpzOwkF", + "aIPuumcFdhwPKj": "HoZauRPJpQVXbpiLZVEJSMDUgqZGBbVGJmKDvAhPmxUdduFVP", + "kSxTHrhafUOFtTRNcTs": 88, + "HbThjVSaOEYsXp": [ + { + "dw": "b", + "jqsZ": "uXPBCtovSqE", + "LyDwPspWbu": "GqLLuzhAfomv" + } + ], + "hXSlwNKxGkXxNum": { + "qrtLaDGRWYwU": [ + { + "CjmJvMKa": 389, + "buPsLrTkBPlzUi": "ohNaqUUXgNWegFJMLqRlSmpjdB", + "BqZv": "ITpSqRRdtpwXSNPxpTKSlyxqpIrmVZHIJDBTSSRpLbrCAMtgmrZtcrZFfdAkcUQVAXgApkdERPvJktFHQVZkloIKCxasee" + } + ] + }, + "BzwVGqXOgsFSnvoiKBgi": null + }, + "IkMUdnfWtCIQXiVHWLMmna": { + "sfsJyHHikG": "OJQzjOGR", + "GExIhvNwzAFoC": "CRMdyBjRVthyOWbvAqyuOLRwmsejtvxObSOkOYyOnqQJrSMSJLOjEeapCSMwuDThjJOKBjFvMKKCftpJwcwdBoPQQ", + "KQnbulNgdRjgvR": "DSItDQNQDOxCGOkzBugnxdrCpMIFysGB", + "urvISwUKEkrbNIzOYTp": 73, + "rVzmkRfjsdNpIh": [ + { + "zG": "s", + "qoXf": "cqPNuTrkNBdaipsQZsboFTjwBpGs", + "hDqUKomOht": "IXeFjZKgCWAxnczhGh" + }, + { + "kj": "y", + "snSW": "qkHnlUjymmqawJbOwbcbZwLddnkFPpzvgbKxSZR", + "LlOTNAEWuu": "wuPqpBbynoqphyetZruBVYrnOFpMFkj" + }, + { + "jz": "V", + "cnGq": "hOeRTXmPJpOJQmVemZLqFNFpvCDuxGDswcCbrHpM", + "traOHspbRX": "nPQVFnTpGKxylFAkymUzHGovzj" + } + ], + "PsAaNeXOJKnDGuv": { + "oxUJcwvEyzyfZiTLed": [], + "uQOOQzWFvsmWbEFiLaIhOrocCZijqPU": [ + { + "dHUMtcWb": 85, + "fqoTKfOeQ": "SNbsylguksFxHzdlb", + "rKEvC": "XFGOcrsIdfhanyWMkLVtntJWCHLZyhAJjdpHuhQdLeQIGkgrJAkHGXgwezQqYnHnresPYzcSoFeHzUQzHsUuccFmhxRsIiZqFT", + "DbPuKJj": "GfbWEWaKAuPkCPpGRLtmxuOAZRDBNjfoiqARoCEG", + "Clne": "olDYCUaLUlEvYNLkjVWlxIkIjaBDUnvPIaikgKESfmFMbanppuAxXzvGxuYNndsxBexWMOSgNxNdcn", + "kZWiLI": 5066.92, + "kUCsVditfgC": "jmXERYF", + "iApmqxbKGX": 902625679990, + "WZimIsfqD": 7276919958509 + }, + { + "YUaixnQc": 985, + "tGlWxeVJk": "cnKiOcwwZIOVeGAeD", + "hGInR": "iUUidOJxPjEmdryOiqmCLbWEbrtBAQrPAkturwfdQrxiazNPuheZlfArEAkndZXcwHqHSjkLVxRrweTdRkvzYdhUyevAgjlAuLkkjJsDSzCPvxxTHFdIbWstDlG", + "JfGqgXr": "wlMhzANfrZJOiQDiCXNoucTTNXdXDcEPKZN", + "pLDp": "vyhDFGSzfZYHXSJBYsfxOfqxoMXLRyQiNPlcBIpGvBdweDQjgDmdDEfxzrHRJNQGPYWNQsdAEmCOuK", + "fEyCzb": 3243.94, + "oTFPnVAOkGb": "gLikIHu", + "ftqVbkPdih": 939431310405, + "KVYkHxRnZ": 5443974824723 + } + ], + "CmzfuVsgGtodifQOUsCbuVlNSe": [] + }, + "FIhZUrphEmlMpwRvXroY": null + }, + "another-level": { + "mlukciiYIy": "zCXvUxXu", + "CnfMDPFZOGQEI": "miXAsAGcDSncucISmpPvVqkRBOMELoCdXeJHNAGfpJkobprShTPAJBngvpkuYneHLsrqsVZkrVCVrmcbuReieATTg", + "GcEdfwLAsprYbk": "MotmAOvgVXsKIhTtCQUyYVviArnBWgYr", + "shnfmTJxNAjCYIRZbqE": 30, + "deep": [ + { + "inside-list": "q-test-value", + "gurT": "hyPIFAsGGjJrqIkvIunZMRFuiAzWUEIf", + "sQunoNuips": "hBPaXgkzgirAtWFRiSzvH" + }, + { + "Ji": "A", + "mzNy": "pRozZecAPsYFfpFKWSMHJkBTNQeQBwdXKSklLSYdCqMm", + "RZFoexDHBd": "ejNlGwvktjcGhoLdebJhryTf" + }, + { + "zI": "f", + "YCLX": "BZsltRfcouxQvlrKimkBEmXSqPeWUbfUUMPPvTCTyzC", + "nATlIsuwIk": "akRjMDGYlmJQdsvbEDxrmOxpgJ" + }, + { + "ZG": "S", + "fsfm": "jpnbkpwONIzyEfCRmfJirTePTPyPLKIUGhIlLHGsva", + "oBqaPDAwdQ": "SOlxsEKyzwvuSRnVudndPDLbKnXVfU" + }, + { + "aX": "J", + "ATcQ": "HIKOIlQLZKFKsGWizKkbltJipVdebSWYieREtglNbVhnmKaDuQIqGG", + "VBixFproZM": "JyyyDXQGGhBGUuvoKRUgCxDisRwktSDAp" + }, + { + "NP": "F", + "gJkc": "YjzqvcTtFpYbMoqWRebzoSCnOOuLjknMuldlVcMIGlcD", + "iWHzDRCesT": "NkyxSwhEHoNQWkrVlATxRFkKZrgmG" + } + ], + "qxjFsOxYrHqndWw": { + "kPFsJUBksPtZGZNYTImXG": [], + "boXLFpUBeyymYVQlONCZqPgs": [ + { + "kXhsgeuH": 645, + "KRJSrwyUw": "rGKdEYaIZlvmGsidj", + "eAbHh": "opnBCinG", + "ePFMEEI": "pviqdZqNDYndpoADMaMypWXoNadIaAMEpONhijsimGNlVKzsvtJxFewDpaFuzrPhYFMMD", + "CFSZ": "GyqWiSKbfFrrFtZIFzYadCwqXKvbQkBHiJMquyxthZXwLEbUmaYUNXiXaLwvaKOImiSiXeXEGXtYYl", + "zZSuDi": 8468.66241833, + "NqRRvrpGAK": "KpabDY", + "vQAYWUCLri": 1337206744292, + "btnUszoxojT": "sCjqoSzCcl", + "lPoQmj": "quJMDF", + "UoWmnAzd": "qdoHexEHdFBxtgzwdwzzEZwRizboXqfAXnhOHnTFjpdZVKHjeVTBRrrVDOukMYYNDeeqN", + "jDJMpKcPP": 8379092631755 + } + ], + "qnrTGJHiIXgpZcXYPkuamvAiXL": [ + { + "emodjnAn": 543, + "BAEnSSMih": "ulaBwyrmoQNwWxZwn", + "dNGno": "NLmGXWOf", + "lPxbHIc": "lwkNVzxUBOQZhsjYpjqcHIdnYVFQaNQpUfWwikaxhs", + "hnph": "BVfWThPsXleSDbysvmGZkIGBKUukiSxStEgczqqmVATdDyNcUZqYDLSReenzPxCUufnGEaesUpFWGb", + "vfIEjn": 3264.24432241, + "fLNcrrBOiS": "MXYFoX", + "HGYipRZebc": 4367194090471, + "NOSgotBWxOP": "zqUwwsQlwV", + "htGzhH": "prNQup", + "hONVdjIl": "CgUJVLGNnqinwWKhNOCPKSkkuZPTkmYgllzBvkgNEf", + "qVphjWUQx": 4327528108500 + } + ], + "IYFDxlctDvPKbXuUPNrFROrtBdKEfx": [], + "WWRwlLMfbVlSzXLvvZhYOuQlpLzUNXhEb": [], + "kUFUnnvpsdiFdxRjqCPubBARkiPuK": [] + }, + "PGHrEwkgDLjXnthXURFV": null + }, + "KNfWgzXAbpOIQzhBCbGqiHh": { + "iDFKxGAvgL": "UXGQvYSY", + "KykgTclosDeBe": "sswTusviDgHWYKdpFOarusGeUNQhhmcCdLAuKNdpFDzkGCjjRjgzgpZfJggzYurFMIvywsBMQrHixUtEJyOfqYoyWr", + "VsiaCVENQIOZkY": "WuNqwWVZQueOVPnXNhjclBKczfvUONmCyZeZUtezFNGvwarXkSo", + "YZxYNVCiWxDzdvefIbg": 56, + "tRKloJtUqMKsXT": [ + { + "eE": "s", + "pvoW": "PseeDBqWKWwRqNWzpKgJoBqAyizyvTexLEaUpCMGMKCs", + "MjOtyZRDjp": "CvSddqRgxWPEiBSETqycHhVFPdkWudowZUX" + } + ], + "OEOidnwMIXvaOTp": { + "GgALdhujAGMZmDPkJagDhQriYcqAWmNAfIN": [] + }, + "kdLfKIhGnAFChahXtqMd": null + }, + "NPnmHgQRSnSiCAfQpNYbbOmMOILcsePYj": { + "SDaijJGmnE": "UHtMOOzt", + "ecoBChzAdTzAE": "KtPIdsawotEXCekSGPaySUBzjPfIISnQGQQqjWQHIoNRHvzWmIPIrRPIOZCOAPFSRAOBjbRcHhSlfiJqaRXXTcEzQHGSQrQrB", + "MjnqBzitIOKFuDeTpgQ": 48, + "xdvcHbkHKtQEbq": [ + { + "Cg": "u", + "Iwti": "ddVWdADQypEFcJsdIysGrCoINuwUkofxhDgvZHaWnON", + "exBxcPyYoF": "FZnAbeTpGzswPkpmDREmDiXMZrOcR" + }, + { + "ZT": "Q", + "RqCu": "SDeaqemsIhDICtcCIbejcEFLEzUuYlv", + "EEQCKLbqSF": "JXEABzhSpyTZUNbLNOOjRPovPeVRzD" + } + ], + "ElqrjJJnQtbfYHk": { + "zNBjkzOFcfurjwOflWqoSoJHGcgWt": [], + "RzxxAzSoKflaNflshVFjmgDBVihViQ": [] + }, + "NXpcmgwnbpJgvXSEmZBy": null + }, + "YRWRIllnFNzOFxeOfWsRRW": { + "dRPBQjRsQH": "tsanJRTf", + "dxWTtEeCciZyv": "ZgLZPsRUCfZrDCzjFZugEOrDNQxuWcZlosVsWfVKsRFbwneUmZOVJLRvqSkkqbNWFFdaXovZOzcFQQfpKazMpqXLn", + "lSnqsyYMVcferd": "JIMncVFZVoKTCRRaofAvKELeXCDSvUvAqottR", + "AkTMuJnjHdFOMhdIPvL": 40, + "hGKIvkUJeFpqAiVLTE": 0.1, + "LCbZIgxDMwsfnd": [ + { + "DE": "j", + "DiLd": "yTnKbAhURddC", + "qDomOIBGrK": "jeGXxatqaiMNUS" + } + ], + "yCOvIPbwEFamgrV": { + "IROWYcoirJGdBW": [ + { + "PkfavXEg": 51312, + "SdLdWmbDs": "hxkuAiyaKABojvWUj", + "zqnQMWOJCvi": "CfAkqLnivujzkmSJzLyACUFuqckDZffoFHyLQXPIyJLPUu", + "rfcrKmYGcSez": "qqONyt", + "kXWOBjrahEwH": 688204086555, + "tIoAdvGHvQihUK": null, + "lhnwfonrEgAbIa": null, + "PvpZ": "ErjqcXdIEjxNJKTAtJpiocEGqfrKreFXzybjDaEnMolQIgWFGifJyougqkEnTbtkfnEIHUwwR", + "ovpZOvxuJuiUh": "sJxbgmMCgyRqy", + "iCsefePPEtXwmAFyBAElEF": 1631732229544, + "GVPsrQLeX": 1703394242891 + }, + { + "urKJkPNj": 39788, + "PunDUGyZr": "yeyAAQAgjcwajeHQq", + "kKDyxGuXMvA": "WJtCzEVpqVTt", + "ChBfyLHpYKSZ": "RaALMS", + "LQqsVuXlQyqy": 927018569345, + "ZbhiZXSCKndYVa": null, + "WEaulqQpkCralT": null, + "tRnS": "jywWCrEHUKEOTaMtDNAuoCnKEIvrsDjOnsexbgFFZNMMrncnWrgvBsoblnxDMTriOdtoCfoWR", + "ciiWoRJygyQlz": "sNAYRXLJAJFPy", + "DamhVKfvyPqfQdBxBNrssp": 3740238446611, + "bNRhZXtph": 2276109534140 + } + ] + }, + "marGUjRDbzFHcFEtSLQS": null + }, + "jqBEzDosuKbGPtWADcBrld": { + "zhswOzzqNy": "jfVDhVxc", + "GHibzoBXWVoAF": "vMbAYoftvcAVgQIFAfKZhWiTRdpSZbdbIiMEjZKcahqBxZbiisUYdbSkOJtpFyJSVIBEuJsmUApiDozXMQRoyxOzc", + "NaXQABuwoCQFmK": "wdwZffquHWUHEAuVVTnMBgQghUvcvtVjqcWjVwiNOupUQGTCbaFKfBkXxhe", + "keedCEXRemGflrVZoMj": 54, + "gyIMHdqLNYmsON": [ + { + "it": "PN", + "JzEV": "CWqhQbRLdWHSBNEWslzufvTSjgccnHyg", + "XFUfCUVabj": "CmJKehESMvSGKMOJBggxz" + }, + { + "eR": "Np", + "vJmV": "aRblzAuYCHzKLyos", + "tSMrRZPPXy": "bYeIPQKVuaRagdnIj" + }, + { + "AA": "LH", + "SJIB": "bruXLgKJJpdVnfsIzJwLguJRpeMNgOPQsxMpWoj", + "nfCOviLuVs": "LkRxwSgTsBPdvzkNoynfsOkKPSzHn" + }, + { + "tb": "GI", + "ErmO": "hQXjgkDNCLinoyLdQHL", + "MvqGbTZDhT": "JgbfDZRJeCTcmRWK" + }, + { + "VT": "oh", + "gDVN": "MKpIWDZYowgqqjSZewNfYVtOw", + "jKrlMGMUlt": "zARquavZLTZODgCYAA" + } + ], + "sUyDEIFIDTugdUa": { + "bBhGHevLDSmYvDMRrwyqN": [], + "DyyDdnssgfxkTWVtM": [], + "DiCDIanIMgrIwzSJLJIVxkMQjcTrW": [], + "jyDYYryGeHrOAMiD": [ + { + "vxstfHhp": 46341, + "wliJbJSbktz": "ZUx", + "GVqxRNDAgYD": "gUTfbVwyMd", + "bcreNyUEbk": "tABZayrk", + "klIpCWXleG": "FzMmnuUWZukgLxrLxiqosSnoEhFHBNoQlZwxWMNVQALHlRkUBOHloGthsDnqdedAtINmahFjCd", + "dbEKOKxFkSAjzp": null, + "XibVvl": 51.7, + "uSnRHDd": "xJiLvMvPyCrLNddMxdkUZmhlkdjaborlXLQiyWEw", + "MBxtfwFrI": 9606836466097 + }, + { + "kpguejAy": 5844, + "bmjXJeUlLRJ": "zvo", + "GpkxboHNBTF": "mRhrUJRQaQBwqABISdJDnCeXe", + "pCMZoUMbMI": "COVQnpLf", + "jriMJKkoff": "vEFeSnqGaEFFfDQdAJGutKghdnHuCYuBktxrQjdKjHNtklGSCUkJXtknnwKoncmAknYuWeNJQS", + "goYjxAyLAEGUXk": null, + "AzoQwY": 269.76, + "JkqRgaf": "HSsfSokLjZEkd", + "njmvZzZNz": 5742622133449 + } + ], + "qqfRkAfbZrdgBblbQw": [ + { + "zLemOZoD": 76, + "dmgxURtCw": "mxVBOpcxKNukmzVqO", + "MPzbCW": "StQKfHOtD", + "GRAyU": "DFnbnQSGXiqcwoMJrbvmmBdtNebdXeczi", + "scKgKzI": "hdwAfZDXINklHzpFMnEQdRDtRpcAptQfcfYEexDcnlIRwraJEBmWqvNgZuAFeXhgNedjDvEAvsKftVCcKwiqhVmIlSaE", + "ZOqw": "MzJsFzFqpootUOuThjkvQmhOaWCLOdBnxOEGLrNhqBluEfqFxyuPtNkFtXSMoJtyjYjgKPysZGmptMbDiRJeYAPmG", + "NFwAAG": 5176.72, + "SUEdNZosa": 5197286070086 + } + ] + }, + "TejxCezasCThYeurrEuJ": null + }, + "ZZEnDphijQGNBypYDmQenl": { + "HriFSJFUBh": "VpghnJef", + "MCpSylkvPLeeo": "svLBzYdemMizSdZmlXaKikvvdYyUvgprPOhFvVFAtvjarGfbFiUpLUANrohLYLDSaNycXxCsRxUcbdBBUSoXMsIqt", + "YomEUTirqgfPwN": "JXtPkZQiIvsCVHRfpkfqJKHLYCOiquHwhVyiJYIdhfb", + "WlfvSKaMEwLHHGuNNYD": 67, + "FqeqKtcJBdDmvK": [ + { + "uI": "s", + "aooF": "JzbuBHDlLmqppGuWpPCfJEoZBGbpJZPFfATiD", + "krKqAeKWNf": "LGYqdUWpwcOBVnnKbHJoRjdFv" + } + ], + "TurIqeqrrHSjzYU": { + "IecsBNTrPUdPRUYzOQZUFOdTz": [ + { + "oddxFZnx": 972, + "GvFZyLzIgVvnPsWjHpY": "cqfTUpgjLFUoVYFwO", + "kZCOb": "TtDyFvfP", + "BXvRvLAvzoFNWveNE": "vXGPdtkErdSHKPjEUvXFYIoNbcahzHNQoBWmABTwOBMohAQAdUQwzCiaSffXZDJWaqmSXwwICcLATAGCinP", + "yvSICcAPsMnXbR": "kuRkOMLRoDfaShpfSmQmPUiewgTSONhJqLrlKnenTOwEOGLhsUgTMjAIsCPjekPs", + "nTvsFY": 1983.25775195, + "ObKvAzEFewB": "hCrgXDlFqO", + "AeuSYLmSU": 3997831424599, + "wDkPbqWzT": "mPmsnzXqwQchooZnqrHkkIbkUChJcBevlNg", + "VFSdwye": "SxCrJzbfARzwOTQczcXZcCk", + "yxDJ": "DTMGGglkCvYvWDJdFkRRznBJvTIxlyuCZafUkCDbxdRdKKPfkOVpGqPZrwqQdHGLdJPkbqNRVHrczJyNfqhbnsodCVeFkT" + } + ] + }, + "dfmuLUhhXdftfnMaooTI": null + }, + "QtQYmzdOGKeW": { + "lEJXCBlUOe": "ScVeyfKi", + "EscHtUjObLyZk": "eTTtrjaVmFUadljRGOhUbUPgibwpYQDdMWBmNABzQvrxSUCZjxvTfWsQkawqcXkJkoAbKZZCcO", + "gBTtAaJyaUkeAL": "tQRQIvvXCOSIpPBSocMHVGNQoNqpUBcpOeX", + "JoBLSfQLRCwpPLBsYYT": 28, + "lvJIaKfeVhdqrG": [ + { + "Fl": "x", + "HExS": "oTOOYUYhGVRHOEXYPwFEqCGeTTmmMcob", + "hiObWgvPXw": "NkOzxqozkvNlezkrH" + } + ], + "ifBxEkXcLTKbFrF": { + "dGCslZCVAxJmIqCCQ": [ + { + "OVYQSUTR": 99, + "ZbSpZnhEOUGRSGLwKJdrWCEERi": "aUdQgZIpPQo", + "vXzoxwmVKVNbwdqHkpFAgJurxPhu": "TMbaH", + "khtJjmTVDdgQOnVEipdYzyLRGmrVup": "NueamThyWdirY", + "NnLfXsmxdfSjTDsaaIcVkhbG": "joOoS", + "oZxPqrebudrHYJeEskjVXgWrFHdYiMCXA": "lHWpRBTHelNgEINA", + "DVayuivgKJoccQRdakuuqJUhRMQ": "NfSNWsQ", + "qnGLDWFrKozkQpVIXCneczU": "hDCunOHGHesvjdIZiUT", + "mXWpmlVqBYTguvDmM": "DTBHXrr", + "rfMhBuWPUZKtzKHlRetzPCOiBK": "loqavRTIYkZWUYDmVRfXaa", + "jNieTWhAammmjLebOpop": "LtLQxouUfXwEihgcTCUOLqhtfEKpKUNxVFKr", + "MlETPKr": 966.76942147 + } + ] + }, + "RCKbeFLEVcVVgCToUjQr": null + }, + "FsJyBjQiC": { + "wrmASxpQrD": "NSsgTqut", + "mKqsjCGnnWZnX": "xFwvsHFOlqJqUDFUMXAzOqCAgfIKFfcIgfiiQmMhcmgtTMRRjbEOdcelghOiBOWnTwaHWioPYDmYjpydHZzslSb", + "DIihcGMzeSncgU": "MofiBjYGXcOBoDDDCeltebYnFgujQhKpBWNathbIyfcSeW", + "kDnJgAckltZpkiRgvgU": 15, + "JCwUZVopvfpPSj": [ + { + "iW": "P", + "cOBY": "UQNqgCIerPNslAatZubiGylLRIITOmvgxtsj", + "cXsoviCTgK": "GDYppAXPxwXdasqmXTlZWw" + }, + { + "Eb": "C", + "UaBw": "tkUOIBcesFiHSySbJPsWvFUzeYbMcBQCtjXt", + "tCwwFJRAlg": "IdjYnMVILDzuWarnlpovSl" + } + ], + "RxpKDunHqEGslVE": { + "FnoKxBiaAmkmVcnVgthJCm": [], + "WcPolxGTZctqgjVSOHXDWF": [ + { + "TxPPNcqY": 79, + "ssbyaGwnbSKqdwXSmBp": "YrPjpBNV", + "EydDkRvqINikusKKuIm": "fCmfcwnliJlqqjJWBBPiopaTkwShykZoLmXwLPujuyethKpVwrUx", + "KRhbOemIgEIBEMfTTmAW": "egsabOQzBwlGrcezEFGiK", + "cQPk": "BAiHhexdiNcxazZAMtZQiPdECNPoqzsOsbSqZ", + "IoVeYA": 578754, + "eGxJLbikzmYG": 6308740477591, + "IQgOYkY": null + } + ] + }, + "VgcGHHmAGmiunYchgZSy": null + }, + "ZrEhPOLhT": { + "ThOhSuEhkf": "cMLJWfEd", + "JVOajxZCbdyuA": "cxaFUMiUyCIaLwYVwzoizJGeiDSSWyNlPobKLGdIMfDNIkXjtWyADbaidasQUPFWbi", + "eCEkbtwEfreMVu": "UmDFqKGDSbfSREnltivyQIAkRjRCrOSDMZsVnWEBumJAKGfEndHYhhepvtCuEWvuKEVGWaytoIKXPfyAulWhva", + "ZcWVqhvhpGjqRaUepPm": 13, + "AAVUVpQBzqOdnf": [ + { + "zs": "f", + "myMw": "VfkIFLvROCCkQoUApAnoahH", + "RZEQcEjWVL": "wvNUPkVOZNEFeBNjT" + } + ], + "XgZpFrSFdfOaiyG": { + "EOpkfIwYsqMJVEuCd": [ + { + "WNWqbIGE": "KV", + "WBelZShKJQOfrdzaHmeB": 5472896691686, + "JBIXmFBrqTZCrFiRIsX": 2537640159589, + "ZqeyuVaHEzqGguT": "mU", + "IGGwKTUNVuIqWhHxguJ": 920159032553, + "FrXZApVt": "iw", + "PwKyEEv": "WVgel", + "pzerZSUF": "OeexCJqW", + "iEZNSXUzExuGRBCJPpfSYAjKGVMySEg": "Xxod", + "BYeMnDMghzdu": "VmhfTPb", + "RAfvTTlXFndzMdzQ": "DijII", + "lFyvSptmIXLEaCITguUlOWUiKinU": "G", + "ocjcEOUYvrjuXHGcPvMZZLanWfVO": "s", + "VAvZVQCr": 56168, + "cNuPEdjOOBIflxU": "zrlEWdItNm", + "CdivJDXYCdDGCKUwvYzGhc": "RLQNkpniJf", + "TxUWBLLBIvWnLWU": "gNdlqeZMWb" + } + ] + }, + "mNeCoNPnyAGmHbaKPcew": null + }, + "iSdPgmIL": { + "PQWhZZAAmc": "KaxKwOfV", + "lBixuJnwKkTXb": "mdYfMahBCGKxYxYUzmuLWatjbvwoEJpvINrBfIRufZilKWEBBhTNVfQNGacQLFrbBPYKrZ", + "thwyvLhRZtMEXp": "CfmYqPuDqxdozCexWCVbAMhFjMADKtoJAVooKRavwe", + "XBwebaSjudhpIdegNuX": 41, + "PVEhBcIvAEUExR": [ + { + "hP": "b", + "ZREX": "yGjjCFbIHmChGFjCwUWPCL", + "fSuYODYuTI": "XSmBDnTzFsWKfPrSZtNlw" + }, + { + "xk": "u", + "MaTZ": "nHYbQnreirVRtzxtNBZZxAiPdOkMfKbTAumbOhIHTtZe", + "aeELNUjGXc": "ckfAhwDcStirCeYjEiDohaqYZCubwHlDosxRy" + }, + { + "ip": "D", + "IeZa": "dIoIXtndoYuPqtFWpGPNhrICQxGGtZHwNaNMPCfwsgqs", + "MLHSeWQvun": "asWubIslOzHcXEvKvmgFmLXOoPVBXWSZZLjgKK" + }, + { + "KL": "a", + "Deci": "LqYMdCjQvypYEYeqfkZxQZSyNOuchvzxbPYiqrPOyjxA", + "RGdhviYBSA": "tYysPwlcraDHTaJOAhDOqHgHrnDtgQUtXdQvs" + }, + { + "ui": "t", + "uRPi": "BlzWoFrIFrYNeYFJhWDgiEz", + "pOfcXLFiRG": "ylYemBXNczSbqgHiMgBPPmLu" + }, + { + "Am": "F", + "OjNZ": "fQfHSNQqHBCtZcwhcAKyqxzdFfIIOxMftGKplAoAkwjgOhl", + "SvFMBmUzak": "UYsxRElPxuenwTrLascZSuadKdLlT" + }, + { + "bO": "K", + "sidr": "PjqwXqNtAGnSQyv", + "tqFzZUMriu": "dDLBwYlhxSaW" + } + ], + "mzIDMiArtQSpMXe": { + "PvZUFGOrSQiKVPtioChPn": [], + "bTwocvbiAytXxsMDuWWkobDytxmCDrpvfvrmw": [], + "dsckhTZaxeCoMoutliYFhNKMeggqpifDiaDUiV": [], + "iMJDWUfULWvFEKAzyksTGIwcgEnuBnBCqsAtV": [], + "aFbYQFVXmVCTAVgCFIxjxlWa": [ + { + "rxccKLhC": 607209, + "jxRkiFOszchOWCXsPa": 853415, + "ZFUqqHGtgGfShZrfyLlEpeM": "PU", + "ETALsHZNmhTvtPLQABi": "EPnDNvAMzWyBXZIHiCtdFfZElKCpVelqfjpHAeSjocCczAEUGTQSOxzOELKkmIKsfflKbLczKi", + "hJAcpYcQCTTcMLWHxpBv": "VIClylsnmKYna", + "qgtueiKiivReWVPilYZQDXunxqvlJkXeBF": "fbeTJKqcdPE", + "UFCQRAHGHlptSNswzzhubxWtHadsgZ": 4, + "YwvFAcZpEfsiiCJIxORuIfpQxiQgz": "r", + "dXpmjLAyxkRKZiHeqWMrcnnWgmvgSl": "q", + "WOyHyfMdnEplxmZaTLooHZWChQ": "gudjRcFWOLRERIeKXyOgsPgIXPLM", + "odvUOeunJkgQwlTbGQfMpqQXpWDbxB": 49757, + "sjsEqexwjwmVjTofGNUAkrONNkXxRUeSKJwo": 1, + "XZQdtbutsHYeEkAlSDh": 14902, + "OghMlcTCKykmdSOoMFqKqILVb": 9, + "hLfbsUWGKzNHwJMbstdGnoY": "tEsBbEZL", + "wERJdBMqpOvISKCQbOVUhaqijbPfF": "m", + "HgVrSBmZQAod": "aLPSrNvQ", + "HTMJaQlPdeialUpCrn": "o", + "tRcUUiuNxlFuGwgmqJQnORXNWfWla": "ujjVgiOKgDzaEEgS", + "uQqUWGIGJRXUmuNehmF": "bDkLQRq", + "ZuwOFzVKzhZXgKniCDa": "KlBNidYpPOduorGECuF", + "TeRfmZady": "kJxokCn" + } + ], + "dqvnKDiCkvhCqKrSDGkpRkXCDIftR": [], + "PWHymzgDFOaA": [] + }, + "fEyJNjSyMZPIFepbZogE": { + "ltwjGeZxWeeGELSWMdxFT": [], + "WgRMTIQEsVYDwrkYujshoKPATzuKICzHHyrnW": [], + "CdfTMvbcWnDzROPJLmRTHXBkYqlrNfNLfqrzcZ": [], + "FqFcxVmbnaBdBNbzmnpaAxxRnBsDktOpbsvqi": [], + "eGyzHvHntiqnRHfwFkOuOTRm": [ + { + "ZaLEuyOQ": 551336, + "JbjQRdfWNlihlrTTNe": 665065, + "VTdVCMIYsielRhFvXgKeLsK": "YV", + "uEYAOFxlVuBZlSlReeF": "zYvYQKZfkCNnxyrirHQaILExJKmNbzjGSOPBQicLZRjpgMjpCkVshOxoCReMvuwLKGVYfseZSh", + "iNLaNOeehzRdsLrCqkJK": "BHxezgseqMKZf", + "dukMUTiUlQZQUufztKLovwiQxschLRsdOW": "PnhNVRmJNGJ", + "rcSjXuIaGcfuDrQtTmuXXEgcfyniLe": 1, + "WJxbdGMIEbrjbHnzKYHCfjMyBrTYV": "y", + "sEyFRkVqMpCXQlBUVbLRYZwtaDyoPN": "t", + "kfjgJjpqynKLMhDyDOWmtHeHjP": "WnHxhgOETDJUITCjlBylUrscDSYK", + "LejvWPtJwajVLTLdDcdaEMTXfXXMLr": 56303, + "ZGovOsYyOKxOQsOLobkdhqyZQjsSnJrADkuI": 5, + "oJbBWMqlPQjuRRcxeab": 38262, + "EKljILsmyegQoCpgxiDZUHqRn": 9, + "tIzcjBaZfVEGVHDdzlSERWY": "EZzWUFaa", + "kSwZsdMwneegDrbDtrqDrsHCkDhXm": "V", + "LdyxtvxSlvoO": "hhOEdElb", + "XXhMDijIpqbbFGeWSL": "s", + "HkKEgyKDWCiuhraOmUMtTJwCbRurs": "IDQCaeYIKCokMaKZ", + "vxTksqnWOuOurGvqmCz": "YCHSCGH", + "JNgtIFmpcCKZNYcdBcL": "uVsineYMkkJqRxVcNXc", + "TpelcIFbX": "bXyOyCr" + }, + { + "SALUwgGO": 422160, + "vUPoqCeyXZYVyKdDez": 110181, + "wuudGJomXEbQerkPAeuiHdQ": "Rq", + "HJaHAJDwUxlDJVZEJtL": "IADfuWftNRNMWsbTqAlTcebAdSriMXAGtODjtVefGcipUuhpcpXvNUAACECiCHGqldwqyQSjzk", + "lOoqUabKofbFaFNhWAce": "vHOeURaAPZKZo", + "fPAsoVQTMaYtCLUIhtJSoEXwmQiEueBOoT": "pbMtzhGNFuw", + "MkopzNpKrfqKMvfQudArubAIJCKaPn": 1, + "mGdnyuYRkoepaFhWcvurdzFptTfpY": "q", + "XXFafRRdtZrjfGEqUJjsKFHFJNkDgb": "m", + "OfYzQuLFBLIztNRebcrgApfXFr": "CKWuWfYuemwUuZHASdutpkyZDEiCz", + "tfCWhBWHBAPCjiVflgHumZshNyDlnX": 61351, + "xFxUmTfoQRkBoxjUObDwGRLuNRoPqTqSgOZC": 4, + "NiDyWWTaTgRPgwOkhKm": 24342, + "UShOPbdowGsHPaVZIoJGAulgU": 6, + "maREjMjuZKBYfhjpKfApJNJ": "DCftkfKw", + "YWURXoXhvPTvsLYSSWJrQvuaESwjZ": "i", + "kQbsQaAUkKui": "UtGEJuCQ", + "JFXelEkDJbobOlqITR": "Z", + "WSZyvSdVSmEtDPuvaxhjvZMYPTHFU": "gzuAUDiKhSSKzUvD", + "CXNQtGtVVgZuQDmpIVl": "gClSrZn", + "hsOsbDuVUxYZshFaHYw": "gxnNDDnMkpNTygSQFFH", + "sYprmhCGN": "ilfhBoD" + }, + { + "HYYoAEXq": 888873, + "sdxgslAUiBmttwDBlI": 579463, + "nAyDIUtNKsxpDdVXDIbuQFj": "ay", + "CrgHZFdSEkIiBzEFsSn": "pAXHeVZezbDAFBVonEDmbwksjOkCkCrRsyWBvAKMhogmhaWUUJgvaHylPFeGqooHqiYPEJBbrK", + "AllKJtgeiHqNEMNYyAGg": "rApYKQbcQvcHf", + "EehtqHSYQeVhGSrxPdTwDpOpZtBOWryJui": "kCZEvWOCHBY", + "CSDFuGPObwocJLQjkMSmeNaHGwkdiT": 3, + "gIFGmniKsjcrTXBpdjXLgqAuTgNLH": "C", + "OAwnMHqtoUoyYeIffrNhMYpEcOhLgG": "e", + "LmEHwVpaVRpISbUSvyRQvGEsYB": "ajUjUMkYYtrLOzLyCRnrGIyHSPcMP", + "kfdrIuzfuMJNLmTaGuLsJgJIrzcLte": 86692, + "WzQgVsABgeBuYJagjNwvMqxbDsKsJQlqhNPq": 5, + "KDMMcdELUBZVMRQrFaq": 49970, + "UNZFnVUvWmdYvdMVYmMEMtCiR": 5, + "PTfmooQOsfhdpOoJZaIoRbP": "EIcImRxG", + "wCPtSYedohQXjBSTsVRzBninLgUWN": "R", + "tKweVWmpUfxI": "rXHiyDYd", + "xFXsHVjXcFVmvZmQLp": "A", + "ScZSUFQCzCspzjOSRdyPTukuCsfYM": "rZuKxCcnsFVYMRmO", + "LDcQksbwplenjbJvDBW": "UoiDLmz", + "INZskzBorkuzkhKNOps": "eUbTWBkljMMqbusgukl", + "mrfTmDiHW": "LFCjGfg" + }, + { + "EjNCWrFb": 742413, + "NMVvbenrZuBgTDUZCp": 186545, + "BUtfbTGYlHreDCxyWILogKd": "Mz", + "NKrESnACBnpJJHjmkTZ": "qASBSQVhyRLbdZdVxwzflldWiPJHVTVKiPYYPfEfCCbhdoOqFxDcioreqnsJfTpnRqQgygySaZ", + "aiNcHSGPLDbbWgCNwYur": "AYNcpKIqqjMyq", + "ILZhJVUfFssjrztzcpVVDvKkQYZzwjCoxN": "WnCnNqoerIc", + "lsLxVCBnLkmJzHHGiPTuRjGiOMsdcl": 1, + "OpAEZwatpCTUKdNeGhdrNYKiDCjKF": "H", + "oieUmtelFLuhNltJTbpnlDUrumqEUh": "w", + "HbCaXRqyuyMOwTBlGnNZXJFGxr": "tNegGiMyeuEJjvmLBHaftebPfTUgt", + "nqwdZutJpaaJnWIpexLGvelyBzAQAR": 23649, + "rcDqtgcbrVcihshHVKGJKswBScQkpIOdsOFv": 7, + "HIEJnealWLrYSoncIBg": 86311, + "MVXXrgZRsbVJXHdUHaCgKnwiV": 1, + "WKPsIWKDqDtcRBsQwualDYd": "EHpHqhZh", + "IxwTNNpzhgXrFgDdfJUrPSJJlXwIv": "n", + "iofIoBqJwtem": "msvMqPBN", + "QLCHAVqTVdLUOFjHXA": "z", + "NsHhiTPivEbEQYEREvxCXUUfgVNDb": "IAUoWhCriVcellGN", + "SrpJdwlzurxhyTYVZNd": "DLGNoPy", + "zzjpPxKOqxtIgPmKnhI": "sSOJzIbjrPSjjFECexD", + "ICTfrcAwa": "ilXpLHy" + } + ], + "RGTbNGqucucZmQwmPnzuMMGgpBYjh": [], + "QzSZKtDHHvnV": [] + } + } + }, + "uiINEgYLQtWZTKPk": {} + }, + "payloadClaimCheck": null + } +} diff --git a/tests/unit/services/events/test_event_ruler.py b/tests/unit/services/events/test_event_ruler.py new file mode 100644 index 0000000000000..1d968407556f3 --- /dev/null +++ b/tests/unit/services/events/test_event_ruler.py @@ -0,0 +1,69 @@ +import pytest + +from localstack.services.events.event_rule_engine import EventRuleEngine + + +class TestEventRuler: + @pytest.mark.parametrize( + "input_pattern,flat_patterns", + [ + ( + {"filter": [{"anything-but": {"prefix": "type"}}]}, + [{"filter": [{"anything-but": {"prefix": "type"}}]}], + ), + ( + {"field1": {"field2": {"field3": "val1", "field4": "val2"}}}, + [{"field1.field2.field3": "val1", "field1.field2.field4": "val2"}], + ), + ( + {"$or": [{"field1": "val1"}, {"field2": "val2"}], "field3": "val3"}, + [{"field1": "val1", "field3": "val3"}, {"field2": "val2", "field3": "val3"}], + ), + ], + ids=["simple", "simple-with-dots", "$or-pattern"], + ) + def test_flatten_patterns(self, input_pattern, flat_patterns): + engine = EventRuleEngine() + assert engine.flatten_pattern(input_pattern) == flat_patterns + + @pytest.mark.parametrize( + "input_payload,flat_patterns,flat_payload", + [ + ( + {"field1": "val1", "field3": "val3"}, + [{"field1": "val1", "field3": "val3"}, {"field2": "val2", "field3": "val3"}], + [{"field1": "val1", "field3": "val3"}], + ), + ( + {"f1": {"f2": {"f3": "v3"}}, "f4": "v4"}, + [{"f4": "test1"}], + [{"f4": "v4"}], + ), + ( + {"f1": {"f2": {"f3": {"f4": [{"f5": "v5"}]}, "f6": [{"f8": "v8"}]}}}, + [{"f1.f2.f3": "val1", "f1.f2.f4": "val2"}], + [{}], + ), + ( + {"f1": {"f2": {"f3": {"f4": [{"f5": "v5"}]}, "f6": [{"f7": "v7"}]}}}, + [{"f1.f2.f3.f4.f5": "val1", "f1.f2.f4": "val2"}], + [{"f1.f2.f3.f4.f5": "v5"}], + ), + ( + {"f1": {"f2": {"f3": {"f4": [{"f5": "v5"}]}, "f6": [{"f7": "v7"}]}}}, + [{"f1.f2.f3.f4.f5": "test1", "f1.f2.f6.f7": "test2"}], + [{"f1.f2.f3.f4.f5": "v5", "f1.f2.f6.f7": "v7"}], + ), + ], + ids=[ + "simple-with-or-pattern-flat", + "simple-pattern-filter", + "nested-payload-no-result", + "nested-payload-1-match", + "nested-payload-2-match", + ], + ) + def test_flatten_payload(self, input_payload, flat_patterns, flat_payload): + engine = EventRuleEngine() + + assert engine.flatten_payload(input_payload, flat_patterns) == flat_payload