|
@@ -43,6 +43,48 @@ from sentry.replays.lib.new_query.fields import ColumnField, FieldProtocol
|
|
|
from sentry.replays.usecases.query.fields import ComputedField, TagField
|
|
|
from sentry.utils.snuba import raw_snql_query
|
|
|
|
|
|
+VIEWED_BY_ME_KEY_ALIASES = ["viewed_by_me", "seen_by_me"]
|
|
|
+NULL_VIEWED_BY_ID_VALUE = 0 # default value in clickhouse
|
|
|
+
|
|
|
+
|
|
|
+def handle_viewed_by_me_filters(
|
|
|
+ search_filters: Sequence[SearchFilter | str | ParenExpression], request_user_id: int | None
|
|
|
+) -> Sequence[SearchFilter | str | ParenExpression]:
|
|
|
+ """Translate "viewed_by_me" as it's not a valid Snuba field, but a convenience alias for the frontend"""
|
|
|
+ new_filters = []
|
|
|
+ for search_filter in search_filters:
|
|
|
+ if (
|
|
|
+ not isinstance(search_filter, SearchFilter)
|
|
|
+ or search_filter.key.name not in VIEWED_BY_ME_KEY_ALIASES
|
|
|
+ ):
|
|
|
+ new_filters.append(search_filter)
|
|
|
+ continue
|
|
|
+
|
|
|
+ # since the value is boolean, negations (!) are not supported
|
|
|
+ if search_filter.operator != "=":
|
|
|
+ raise ParseError(f"Invalid operator specified for `{search_filter.key.name}`")
|
|
|
+
|
|
|
+ value = search_filter.value.value
|
|
|
+ if not isinstance(value, str) or value.lower() not in ["true", "false"]:
|
|
|
+ raise ParseError(f"Could not parse value for `{search_filter.key.name}`")
|
|
|
+ value = value.lower() == "true"
|
|
|
+
|
|
|
+ if request_user_id is None:
|
|
|
+ # This case will only occur from programmer error.
|
|
|
+ # Note the replay index endpoint returns 401 automatically for unauthorized and anonymous users.
|
|
|
+ raise ValueError("Invalid user id")
|
|
|
+
|
|
|
+ operator = "=" if value else "!="
|
|
|
+ new_filters.append(
|
|
|
+ SearchFilter(
|
|
|
+ SearchKey("viewed_by_id"),
|
|
|
+ operator,
|
|
|
+ SearchValue(request_user_id),
|
|
|
+ )
|
|
|
+ )
|
|
|
+
|
|
|
+ return new_filters
|
|
|
+
|
|
|
|
|
|
def handle_search_filters(
|
|
|
search_config: dict[str, FieldProtocol],
|
|
@@ -163,6 +205,9 @@ def query_using_optimized_search(
|
|
|
SearchFilter(SearchKey("environment"), "IN", SearchValue(environments)),
|
|
|
]
|
|
|
|
|
|
+ # Translate "viewed_by_me" filters, which are aliases for "viewed_by_id"
|
|
|
+ search_filters = handle_viewed_by_me_filters(search_filters, request_user_id)
|
|
|
+
|
|
|
can_scalar_sort = sort_is_scalar_compatible(sort or "started_at")
|
|
|
can_scalar_search = can_scalar_search_subquery(search_filters)
|
|
|
|