From bc2f5b2c3256df94efd5614bc607aafdce60814a Mon Sep 17 00:00:00 2001 From: mathiasg Date: Fri, 17 Nov 2023 17:15:04 -0500 Subject: [PATCH 1/4] FIX: Safer query construction --- migas/operations.py | 113 ++++++++++++++++++++++++-------------------- 1 file changed, 62 insertions(+), 51 deletions(-) diff --git a/migas/operations.py b/migas/operations.py index 7bce666..13619a2 100644 --- a/migas/operations.py +++ b/migas/operations.py @@ -4,14 +4,18 @@ from __future__ import annotations import dataclasses +import enum +import json import typing as ty import warnings from migas.config import Config, logger, telemetry_enabled from migas.request import request -FREE = '"{}"' # FREE text fields -FIXED = '{}' # FIXED text fields +class TextType(enum.Enum): + LITERAL = 1 + FREE = 2 + ERROR = '[migas-py] An error occurred.' @@ -48,23 +52,23 @@ class AddBreadcrumb(Operation): operation_type = "mutation" operation_name = "add_breadcrumb" query_args = { - "project": FREE, - "project_version": FREE, - "language": FREE, - "language_version": FREE, + "project": TextType.FREE, + "project_version": TextType.FREE, + "language": TextType.FREE, + "language_version": TextType.FREE, "ctx": { - "session_id": FREE, - "user_id": FREE, - "user_type": FIXED, - "platform": FREE, - "container": FIXED, - "is_ci": FIXED, + "session_id": TextType.FREE, + "user_id": TextType.FREE, + "user_type": TextType.LITERAL, + "platform": TextType.FREE, + "container": TextType.LITERAL, + "is_ci": TextType.LITERAL, }, "proc": { - "status": FIXED, - "status_desc": FREE, - "error_type": FREE, - "error_desc": FREE, + "status": TextType.LITERAL, + "status_desc": TextType.FREE, + "error_type": TextType.FREE, + "error_desc": TextType.FREE, }, } fingerprint = True @@ -114,21 +118,21 @@ class AddProject(Operation): operation_name = "add_project" query_args = { "p": { - "project": FREE, - "project_version": FREE, - "language": FREE, - "language_version": FREE, - "is_ci": FIXED, - "status": FIXED, - "status_desc": FREE, - "error_type": FREE, - "error_desc": FREE, - "user_id": FREE, - "session_id": FREE, - "container": FIXED, - "user_type": FIXED, - "platform": FREE, - "arguments": FREE, + "project": TextType.FREE, + "project_version": TextType.FREE, + "language": TextType.FREE, + "language_version": TextType.FREE, + "is_ci": TextType.LITERAL, + "status": TextType.LITERAL, + "status_desc": TextType.FREE, + "error_type": TextType.FREE, + "error_desc": TextType.FREE, + "user_id": TextType.FREE, + "session_id": TextType.FREE, + "container": TextType.LITERAL, + "user_type": TextType.LITERAL, + "platform": TextType.FREE, + "arguments": TextType.FREE, }, } fingerprint = True @@ -174,20 +178,20 @@ class CheckProject(Operation): operation_type = "query" operation_name = "check_project" query_args = { - "project": FREE, - "project_version": FREE, - "language": FREE, - "language_version": FREE, - "is_ci": FIXED, - "status": FIXED, - "status_desc": FREE, - "error_type": FREE, - "error_desc": FREE, - "user_id": FREE, - "session_id": FREE, - "container": FIXED, - "platform": FREE, - "arguments": FREE, + "project": TextType.FREE, + "project_version": TextType.FREE, + "language": TextType.FREE, + "language_version": TextType.FREE, + "is_ci": TextType.LITERAL, + "status": TextType.LITERAL, + "status_desc": TextType.FREE, + "error_type": TextType.FREE, + "error_desc": TextType.FREE, + "user_id": TextType.FREE, + "session_id": TextType.FREE, + "container": TextType.LITERAL, + "platform": TextType.FREE, + "arguments": TextType.FREE, } selections = ('success', 'flagged', 'latest', 'message') @@ -216,10 +220,10 @@ class GetUsage(Operation): operation_type = 'query' operation_name = 'get_usage' query_args = { - "project": FREE, - "start": FREE, - "end": FREE, - "unique": FIXED, + "project": TextType.FREE, + "start": TextType.FREE, + "end": TextType.FREE, + "unique": TextType.LITERAL, } @@ -273,8 +277,15 @@ def _parse_format_params(params: dict, query_args: dict) -> str: val = params[qarg] if isinstance(val, bool): val = str(val).lower() - val = qval.format(val) - query_inputs.append(f'{qarg}:{val}') + + if qval.name == 'FREE': + fval = json.dumps(val) + elif qval.name == 'LITERAL': + fval = val + else: + logger.error('Do not know how to handle type %s', qarg.name) + fval = '' + query_inputs.append(f'{qarg}:{fval}') elif isinstance(qval, dict): vals = _parse_format_params(params, qval) From 7b48abebb9fc77580a2de01f1f5c37ac74f9fc4d Mon Sep 17 00:00:00 2001 From: mathiasg Date: Fri, 17 Nov 2023 17:15:41 -0500 Subject: [PATCH 2/4] FIX: Fallback to Exception __str__ --- migas/error/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migas/error/base.py b/migas/error/base.py index 37c8ff1..18c18c8 100644 --- a/migas/error/base.py +++ b/migas/error/base.py @@ -21,7 +21,7 @@ def inspect_error(error_funcs: dict | None = None) -> dict: etb = sys.last_traceback if err and etype: - evalue = err.args[0] + evalue = err.args[0] if err.args else str(err) ename = etype.__name__ if isinstance(error_funcs, dict) and ename in error_funcs: From 01b8b7a322e222e0b033c9bff788bd3cf36f0185 Mon Sep 17 00:00:00 2001 From: mathiasg Date: Fri, 17 Nov 2023 17:24:07 -0500 Subject: [PATCH 3/4] RF: Enum name --- migas/operations.py | 102 ++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/migas/operations.py b/migas/operations.py index 13619a2..ac2b887 100644 --- a/migas/operations.py +++ b/migas/operations.py @@ -12,9 +12,9 @@ from migas.config import Config, logger, telemetry_enabled from migas.request import request -class TextType(enum.Enum): - LITERAL = 1 - FREE = 2 +class QueryParamType(enum.Enum): + LITERAL = enum.auto() + TEXT = enum.auto() ERROR = '[migas-py] An error occurred.' @@ -52,23 +52,23 @@ class AddBreadcrumb(Operation): operation_type = "mutation" operation_name = "add_breadcrumb" query_args = { - "project": TextType.FREE, - "project_version": TextType.FREE, - "language": TextType.FREE, - "language_version": TextType.FREE, + "project": QueryParamType.TEXT, + "project_version": QueryParamType.TEXT, + "language": QueryParamType.TEXT, + "language_version": QueryParamType.TEXT, "ctx": { - "session_id": TextType.FREE, - "user_id": TextType.FREE, - "user_type": TextType.LITERAL, - "platform": TextType.FREE, - "container": TextType.LITERAL, - "is_ci": TextType.LITERAL, + "session_id": QueryParamType.TEXT, + "user_id": QueryParamType.TEXT, + "user_type": QueryParamType.LITERAL, + "platform": QueryParamType.TEXT, + "container": QueryParamType.LITERAL, + "is_ci": QueryParamType.LITERAL, }, "proc": { - "status": TextType.LITERAL, - "status_desc": TextType.FREE, - "error_type": TextType.FREE, - "error_desc": TextType.FREE, + "status": QueryParamType.LITERAL, + "status_desc": QueryParamType.TEXT, + "error_type": QueryParamType.TEXT, + "error_desc": QueryParamType.TEXT, }, } fingerprint = True @@ -118,21 +118,21 @@ class AddProject(Operation): operation_name = "add_project" query_args = { "p": { - "project": TextType.FREE, - "project_version": TextType.FREE, - "language": TextType.FREE, - "language_version": TextType.FREE, - "is_ci": TextType.LITERAL, - "status": TextType.LITERAL, - "status_desc": TextType.FREE, - "error_type": TextType.FREE, - "error_desc": TextType.FREE, - "user_id": TextType.FREE, - "session_id": TextType.FREE, - "container": TextType.LITERAL, - "user_type": TextType.LITERAL, - "platform": TextType.FREE, - "arguments": TextType.FREE, + "project": QueryParamType.TEXT, + "project_version": QueryParamType.TEXT, + "language": QueryParamType.TEXT, + "language_version": QueryParamType.TEXT, + "is_ci": QueryParamType.LITERAL, + "status": QueryParamType.LITERAL, + "status_desc": QueryParamType.TEXT, + "error_type": QueryParamType.TEXT, + "error_desc": QueryParamType.TEXT, + "user_id": QueryParamType.TEXT, + "session_id": QueryParamType.TEXT, + "container": QueryParamType.LITERAL, + "user_type": QueryParamType.LITERAL, + "platform": QueryParamType.TEXT, + "arguments": QueryParamType.TEXT, }, } fingerprint = True @@ -178,20 +178,20 @@ class CheckProject(Operation): operation_type = "query" operation_name = "check_project" query_args = { - "project": TextType.FREE, - "project_version": TextType.FREE, - "language": TextType.FREE, - "language_version": TextType.FREE, - "is_ci": TextType.LITERAL, - "status": TextType.LITERAL, - "status_desc": TextType.FREE, - "error_type": TextType.FREE, - "error_desc": TextType.FREE, - "user_id": TextType.FREE, - "session_id": TextType.FREE, - "container": TextType.LITERAL, - "platform": TextType.FREE, - "arguments": TextType.FREE, + "project": QueryParamType.TEXT, + "project_version": QueryParamType.TEXT, + "language": QueryParamType.TEXT, + "language_version": QueryParamType.TEXT, + "is_ci": QueryParamType.LITERAL, + "status": QueryParamType.LITERAL, + "status_desc": QueryParamType.TEXT, + "error_type": QueryParamType.TEXT, + "error_desc": QueryParamType.TEXT, + "user_id": QueryParamType.TEXT, + "session_id": QueryParamType.TEXT, + "container": QueryParamType.LITERAL, + "platform": QueryParamType.TEXT, + "arguments": QueryParamType.TEXT, } selections = ('success', 'flagged', 'latest', 'message') @@ -220,10 +220,10 @@ class GetUsage(Operation): operation_type = 'query' operation_name = 'get_usage' query_args = { - "project": TextType.FREE, - "start": TextType.FREE, - "end": TextType.FREE, - "unique": TextType.LITERAL, + "project": QueryParamType.TEXT, + "start": QueryParamType.TEXT, + "end": QueryParamType.TEXT, + "unique": QueryParamType.LITERAL, } @@ -278,7 +278,7 @@ def _parse_format_params(params: dict, query_args: dict) -> str: if isinstance(val, bool): val = str(val).lower() - if qval.name == 'FREE': + if qval.name == 'TEXT': fval = json.dumps(val) elif qval.name == 'LITERAL': fval = val From e8e756d0b9a256b2d8ada724e046d782a7c9f791 Mon Sep 17 00:00:00 2001 From: Mathias Goncalves Date: Fri, 17 Nov 2023 17:36:18 -0500 Subject: [PATCH 4/4] Update migas/operations.py --- migas/operations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migas/operations.py b/migas/operations.py index ac2b887..b42d15e 100644 --- a/migas/operations.py +++ b/migas/operations.py @@ -283,7 +283,7 @@ def _parse_format_params(params: dict, query_args: dict) -> str: elif qval.name == 'LITERAL': fval = val else: - logger.error('Do not know how to handle type %s', qarg.name) + logger.error('Do not know how to handle type %s', qval.name) fval = '' query_inputs.append(f'{qarg}:{fval}')