From a42bb6713f8a0195c38dc92a44047fc28ed37161 Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Tue, 19 Jul 2022 14:47:40 +0200 Subject: [PATCH 01/47] feat(chalice): fixed GraphQL search --- api/chalicelib/core/sessions.py | 18 +++++++++--------- api/schemas.py | 5 ++--- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/api/chalicelib/core/sessions.py b/api/chalicelib/core/sessions.py index 8dc87c90d..738a5e3d9 100644 --- a/api/chalicelib/core/sessions.py +++ b/api/chalicelib/core/sessions.py @@ -390,14 +390,14 @@ def search2_series(data: schemas.SessionsSearchPayloadSchema, project_id: int, d def __is_valid_event(is_any: bool, event: schemas._SessionSearchEventSchema): return not (not is_any and len(event.value) == 0 and event.type not in [schemas.EventType.request_details, - schemas.EventType.graphql_details] \ + schemas.EventType.graphql] \ or event.type in [schemas.PerformanceEventType.location_dom_complete, schemas.PerformanceEventType.location_largest_contentful_paint_time, schemas.PerformanceEventType.location_ttfb, schemas.PerformanceEventType.location_avg_cpu_load, schemas.PerformanceEventType.location_avg_memory_usage ] and (event.source is None or len(event.source) == 0) \ - or event.type in [schemas.EventType.request_details, schemas.EventType.graphql_details] and ( + or event.type in [schemas.EventType.request_details, schemas.EventType.graphql] and ( event.filters is None or len(event.filters) == 0)) @@ -698,12 +698,12 @@ def search_query_parts(data, error_status, errors_only, favorite_only, issue, pr event_where.append( _multiple_conditions(f"main.{events.event_type.REQUEST.column} {op} %({e_k})s", event.value, value_key=e_k)) - elif event_type == events.event_type.GRAPHQL.ui_type: - event_from = event_from % f"{events.event_type.GRAPHQL.table} AS main " - if not is_any: - event_where.append( - _multiple_conditions(f"main.{events.event_type.GRAPHQL.column} {op} %({e_k})s", event.value, - value_key=e_k)) + # elif event_type == events.event_type.GRAPHQL.ui_type: + # event_from = event_from % f"{events.event_type.GRAPHQL.table} AS main " + # if not is_any: + # event_where.append( + # _multiple_conditions(f"main.{events.event_type.GRAPHQL.column} {op} %({e_k})s", event.value, + # value_key=e_k)) elif event_type == events.event_type.STATEACTION.ui_type: event_from = event_from % f"{events.event_type.STATEACTION.table} AS main " if not is_any: @@ -891,7 +891,7 @@ def search_query_parts(data, error_status, errors_only, favorite_only, issue, pr print(f"undefined FETCH filter: {f.type}") if not apply: continue - elif event_type == schemas.EventType.graphql_details: + elif event_type == schemas.EventType.graphql: event_from = event_from % f"{events.event_type.GRAPHQL.table} AS main " for j, f in enumerate(event.filters): is_any = _isAny_opreator(f.operator) diff --git a/api/schemas.py b/api/schemas.py index bacceea78..f0f20e657 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -389,7 +389,6 @@ class EventType(str, Enum): request = "REQUEST" request_details = "FETCH" graphql = "GRAPHQL" - graphql_details = "GRAPHQL_DETAILS" state_action = "STATEACTION" error = "ERROR" click_ios = "CLICK_IOS" @@ -568,9 +567,9 @@ class _SessionSearchEventRaw(__MixedSearchFilter): elif values.get("type") == EventType.request_details: assert isinstance(values.get("filters"), List) and len(values.get("filters", [])) > 0, \ f"filters should be defined for {EventType.request_details.value}" - elif values.get("type") == EventType.graphql_details: + elif values.get("type") == EventType.graphql: assert isinstance(values.get("filters"), List) and len(values.get("filters", [])) > 0, \ - f"filters should be defined for {EventType.graphql_details.value}" + f"filters should be defined for {EventType.graphql.value}" return values From 3528b5e2271290d1b607b2470b6e01ca9fd065fb Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Wed, 20 Jul 2022 11:06:53 +0200 Subject: [PATCH 02/47] fix(ui) - header fixed height --- frontend/app/components/Header/Header.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Header/Header.js b/frontend/app/components/Header/Header.js index 9e6efa0de..9726e83ee 100644 --- a/frontend/app/components/Header/Header.js +++ b/frontend/app/components/Header/Header.js @@ -64,7 +64,7 @@ const Header = (props) => { }, [siteId]) return ( -
+
From 0b176c39e8135778250bf2ac6ce1c64f7dba09db Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Wed, 20 Jul 2022 11:07:12 +0200 Subject: [PATCH 03/47] fix(ui) - session item user name width --- .../app/components/shared/SessionItem/SessionItem.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/app/components/shared/SessionItem/SessionItem.tsx b/frontend/app/components/shared/SessionItem/SessionItem.tsx index aa5cd479d..17b8122c3 100644 --- a/frontend/app/components/shared/SessionItem/SessionItem.tsx +++ b/frontend/app/components/shared/SessionItem/SessionItem.tsx @@ -109,7 +109,7 @@ function SessionItem(props: RouteComponentProps & Props) {
e.stopPropagation()}>
-
+
-
-
{formatTimeOrDate(startedAt, timezone) }
+
+
+ +
{!isAssist && ( <> From 230df86e786442d6d8ea78fd629100910a9e40ae Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Wed, 20 Jul 2022 11:11:50 +0200 Subject: [PATCH 04/47] fix(ui) - site instance --- .../OnboardingTabs/InstallDocs/InstallDocs.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/frontend/app/components/Onboarding/components/OnboardingTabs/InstallDocs/InstallDocs.js b/frontend/app/components/Onboarding/components/OnboardingTabs/InstallDocs/InstallDocs.js index a89904907..d999397f1 100644 --- a/frontend/app/components/Onboarding/components/OnboardingTabs/InstallDocs/InstallDocs.js +++ b/frontend/app/components/Onboarding/components/OnboardingTabs/InstallDocs/InstallDocs.js @@ -4,7 +4,7 @@ import stl from './installDocs.module.css' import cn from 'classnames' import Highlight from 'react-highlight' import CircleNumber from '../../CircleNumber' -import { Slider, CopyButton } from 'UI' +import { CopyButton } from 'UI' import { Toggler } from 'UI'; const installationCommand = 'npm i @openreplay/tracker' @@ -30,8 +30,7 @@ function MyApp() { //... }` -function InstallDocs({ siteId, sites }) { - const site = sites.find(s => s.id === siteId); +function InstallDocs({ site }) { const _usageCode = usageCode.replace('PROJECT_KEY', site.projectKey) const _usageCodeSST = usageCodeSST.replace('PROJECT_KEY', site.projectKey) const [isSpa, setIsSpa] = useState(true) @@ -98,9 +97,6 @@ function InstallDocs({ siteId, sites }) { ) } -// export default InstallDocs - export default connect(state => ({ - siteId: state.getIn([ 'site', 'siteId' ]), - sites: state.getIn([ 'site', 'list' ]), + site: state.getIn([ 'site', 'instance' ]), }))(InstallDocs) \ No newline at end of file From fb3bbbc5c3958d03111a06d40f0608aa5aee5977 Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Wed, 20 Jul 2022 11:47:33 +0200 Subject: [PATCH 05/47] feat(chalice): api_key changes --- api/chalicelib/core/users.py | 1 - ee/api/chalicelib/core/users.py | 1 - 2 files changed, 2 deletions(-) diff --git a/api/chalicelib/core/users.py b/api/chalicelib/core/users.py index 78499860b..1535534c8 100644 --- a/api/chalicelib/core/users.py +++ b/api/chalicelib/core/users.py @@ -241,7 +241,6 @@ def get(user_id, tenant_id): (CASE WHEN role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN role = 'member' THEN TRUE ELSE FALSE END) AS member, - api_key, TRUE AS has_password FROM public.users LEFT JOIN public.basic_authentication ON users.user_id=basic_authentication.user_id WHERE diff --git a/ee/api/chalicelib/core/users.py b/ee/api/chalicelib/core/users.py index 815d39106..ff43cca41 100644 --- a/ee/api/chalicelib/core/users.py +++ b/ee/api/chalicelib/core/users.py @@ -274,7 +274,6 @@ def get(user_id, tenant_id): (CASE WHEN role = 'owner' THEN TRUE ELSE FALSE END) AS super_admin, (CASE WHEN role = 'admin' THEN TRUE ELSE FALSE END) AS admin, (CASE WHEN role = 'member' THEN TRUE ELSE FALSE END) AS member, - api_key, origin, role_id, roles.name AS role_name, From 4d11ddee77cf9505bb4b1e7be05db88b290ee102 Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Wed, 20 Jul 2022 13:30:12 +0200 Subject: [PATCH 06/47] feat(DB): changed autocomplete unique index --- ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql | 2 ++ ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql | 2 +- scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql | 2 ++ scripts/helm/db/init_dbs/postgresql/init_schema.sql | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql b/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql index 1ea5c6ab6..cdf316fa4 100644 --- a/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql +++ b/ee/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql @@ -56,6 +56,7 @@ ALTER TABLE IF EXISTS events.resources PRIMARY KEY (session_id, message_id, timestamp); COMMIT; +CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS autocomplete_unique_project_id_md5value_type_idx ON autocomplete (project_id, md5(value), type); CREATE INDEX CONCURRENTLY IF NOT EXISTS projects_tenant_id_idx ON public.projects (tenant_id); CREATE INDEX CONCURRENTLY IF NOT EXISTS projects_project_id_deleted_at_n_idx ON public.projects (project_id) WHERE deleted_at IS NULL; ALTER TYPE metric_type ADD VALUE IF NOT EXISTS 'funnel'; @@ -211,4 +212,5 @@ $$ END IF; END $$; +DROP INDEX IF EXISTS autocomplete_unique; COMMIT; \ No newline at end of file diff --git a/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql b/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql index 2d1c2b95f..e236ce90e 100644 --- a/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/ee/scripts/helm/db/init_dbs/postgresql/init_schema.sql @@ -658,7 +658,7 @@ $$ project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE ); - CREATE unique index IF NOT EXISTS autocomplete_unique ON autocomplete (project_id, value, type); + CREATE UNIQUE INDEX IF NOT EXISTS autocomplete_unique_project_id_md5value_type_idx ON autocomplete (project_id, md5(value), type); CREATE index IF NOT EXISTS autocomplete_project_id_idx ON autocomplete (project_id); CREATE INDEX IF NOT EXISTS autocomplete_type_idx ON public.autocomplete (type); diff --git a/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql b/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql index c079b9b69..edc751da9 100644 --- a/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql +++ b/scripts/helm/db/init_dbs/postgresql/1.7.0/1.7.0.sql @@ -45,6 +45,7 @@ ALTER TABLE IF EXISTS events.resources PRIMARY KEY (session_id, message_id, timestamp); COMMIT; +CREATE UNIQUE INDEX CONCURRENTLY IF NOT EXISTS autocomplete_unique_project_id_md5value_type_idx ON autocomplete (project_id, md5(value), type); CREATE INDEX CONCURRENTLY IF NOT EXISTS projects_project_id_deleted_at_n_idx ON public.projects (project_id) WHERE deleted_at IS NULL; ALTER TYPE metric_type ADD VALUE IF NOT EXISTS 'funnel'; @@ -199,4 +200,5 @@ $$ END IF; END $$; +DROP INDEX IF EXISTS autocomplete_unique; COMMIT; \ No newline at end of file diff --git a/scripts/helm/db/init_dbs/postgresql/init_schema.sql b/scripts/helm/db/init_dbs/postgresql/init_schema.sql index c96bc9fc9..5f23d7a79 100644 --- a/scripts/helm/db/init_dbs/postgresql/init_schema.sql +++ b/scripts/helm/db/init_dbs/postgresql/init_schema.sql @@ -839,7 +839,7 @@ $$ project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE ); - CREATE unique index autocomplete_unique ON autocomplete (project_id, value, type); + CREATE UNIQUE INDEX autocomplete_unique_project_id_md5value_type_idx ON autocomplete (project_id, md5(value), type); CREATE index autocomplete_project_id_idx ON autocomplete (project_id); CREATE INDEX autocomplete_type_idx ON public.autocomplete (type); From 8ede1d906bf4cb97379310c70a461f0cd182d1db Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Wed, 20 Jul 2022 13:33:16 +0200 Subject: [PATCH 07/47] feat(chalice): changed Dockerfile feat(alerts): changed Dockerfile feat(crons): changed Dockerfile --- api/Dockerfile | 1 + api/Dockerfile.alerts | 1 + ee/api/Dockerfile | 1 + ee/api/Dockerfile.alerts | 1 + ee/api/Dockerfile.crons | 1 + 5 files changed, 5 insertions(+) diff --git a/api/Dockerfile b/api/Dockerfile index 7e99cc457..b92e909e4 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -1,6 +1,7 @@ FROM python:3.10-alpine LABEL Maintainer="Rajesh Rajendran" LABEL Maintainer="KRAIEM Taha Yassine" +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache build-base nodejs npm tini ARG envarg # Add Tini diff --git a/api/Dockerfile.alerts b/api/Dockerfile.alerts index 062a1cb3a..ca714db55 100644 --- a/api/Dockerfile.alerts +++ b/api/Dockerfile.alerts @@ -1,6 +1,7 @@ FROM python:3.10-alpine LABEL Maintainer="Rajesh Rajendran" LABEL Maintainer="KRAIEM Taha Yassine" +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache build-base tini ARG envarg ENV APP_NAME=alerts \ diff --git a/ee/api/Dockerfile b/ee/api/Dockerfile index 9e40d3ca6..4148d1e9c 100644 --- a/ee/api/Dockerfile +++ b/ee/api/Dockerfile @@ -1,6 +1,7 @@ FROM python:3.10-alpine LABEL Maintainer="Rajesh Rajendran" LABEL Maintainer="KRAIEM Taha Yassine" +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache build-base libressl libffi-dev libressl-dev libxslt-dev libxml2-dev xmlsec-dev xmlsec nodejs npm tini ARG envarg ENV SOURCE_MAP_VERSION=0.7.4 \ diff --git a/ee/api/Dockerfile.alerts b/ee/api/Dockerfile.alerts index 6382fa27f..b557dc308 100644 --- a/ee/api/Dockerfile.alerts +++ b/ee/api/Dockerfile.alerts @@ -1,6 +1,7 @@ FROM python:3.10-alpine LABEL Maintainer="Rajesh Rajendran" LABEL Maintainer="KRAIEM Taha Yassine" +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache build-base tini ARG envarg ENV APP_NAME=alerts \ diff --git a/ee/api/Dockerfile.crons b/ee/api/Dockerfile.crons index 155180006..e29b4440f 100644 --- a/ee/api/Dockerfile.crons +++ b/ee/api/Dockerfile.crons @@ -1,6 +1,7 @@ FROM python:3.10-alpine LABEL Maintainer="Rajesh Rajendran" LABEL Maintainer="KRAIEM Taha Yassine" +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache build-base tini ARG envarg ENV APP_NAME=crons \ From c4c99d47afc31852ba6102ab7ad524d9047b5745 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Wed, 20 Jul 2022 11:58:24 +0200 Subject: [PATCH 08/47] chore(docker): Updating docker image for nginx Updated base image. Fixed busybox vulnerability --- scripts/dockerfiles/nginx/Dockerfile | 186 ++++++++++++++++-- .../dockerfiles/nginx/nginx.vh.default.conf | 58 ++++++ 2 files changed, 231 insertions(+), 13 deletions(-) create mode 100644 scripts/dockerfiles/nginx/nginx.vh.default.conf diff --git a/scripts/dockerfiles/nginx/Dockerfile b/scripts/dockerfiles/nginx/Dockerfile index 53da15731..caf6b283b 100644 --- a/scripts/dockerfiles/nginx/Dockerfile +++ b/scripts/dockerfiles/nginx/Dockerfile @@ -1,23 +1,183 @@ -# Ability to add sticky sessions using any parameters -FROM openresty/openresty:buster as builder -workdir /work -ADD https://github.com/openresty/lua-resty-balancer/archive/refs/heads/master.tar.gz . -RUN apt update && \ - apt install gcc make -y && \ - tar -xf master.tar.gz && \ - cd lua-resty-balancer-master && \ - make +# Dockerfile - alpine +# https://github.com/openresty/docker-openresty + +ARG RESTY_IMAGE_BASE="alpine" +ARG RESTY_IMAGE_TAG="3.16" + +FROM ${RESTY_IMAGE_BASE}:${RESTY_IMAGE_TAG} + +LABEL maintainer="Evan Wies " + +# Docker Build Arguments +ARG RESTY_IMAGE_BASE="alpine" +ARG RESTY_IMAGE_TAG="3.16" +ARG RESTY_VERSION="1.21.4.1" +ARG RESTY_OPENSSL_VERSION="1.1.1p" +ARG RESTY_OPENSSL_PATCH_VERSION="1.1.1f" +ARG RESTY_OPENSSL_URL_BASE="https://www.openssl.org/source" +ARG RESTY_PCRE_VERSION="8.45" +ARG RESTY_PCRE_BUILD_OPTIONS="--enable-jit" +ARG RESTY_PCRE_SHA256="4e6ce03e0336e8b4a3d6c2b70b1c5e18590a5673a98186da90d4f33c23defc09" +ARG RESTY_J="1" +ARG RESTY_CONFIG_OPTIONS="\ + --with-compat \ + --with-file-aio \ + --with-http_addition_module \ + --with-http_auth_request_module \ + --with-http_dav_module \ + --with-http_flv_module \ + --with-http_geoip_module=dynamic \ + --with-http_gunzip_module \ + --with-http_gzip_static_module \ + --with-http_image_filter_module=dynamic \ + --with-http_mp4_module \ + --with-http_random_index_module \ + --with-http_realip_module \ + --with-http_secure_link_module \ + --with-http_slice_module \ + --with-http_ssl_module \ + --with-http_stub_status_module \ + --with-http_sub_module \ + --with-http_v2_module \ + --with-http_xslt_module=dynamic \ + --with-ipv6 \ + --with-mail \ + --with-mail_ssl_module \ + --with-md5-asm \ + --with-sha1-asm \ + --with-stream \ + --with-stream_ssl_module \ + --with-threads \ + " +ARG RESTY_CONFIG_OPTIONS_MORE="" +ARG RESTY_LUAJIT_OPTIONS="--with-luajit-xcflags='-DLUAJIT_NUMMODE=2 -DLUAJIT_ENABLE_LUA52COMPAT'" +ARG RESTY_PCRE_OPTIONS="--with-pcre-jit" + +ARG RESTY_ADD_PACKAGE_BUILDDEPS="" +ARG RESTY_ADD_PACKAGE_RUNDEPS="" +ARG RESTY_EVAL_PRE_CONFIGURE="" +ARG RESTY_EVAL_POST_MAKE="" + +# These are not intended to be user-specified +ARG _RESTY_CONFIG_DEPS="--with-pcre \ + --with-cc-opt='-DNGX_LUA_ABORT_AT_PANIC -I/usr/local/openresty/pcre/include -I/usr/local/openresty/openssl/include' \ + --with-ld-opt='-L/usr/local/openresty/pcre/lib -L/usr/local/openresty/openssl/lib -Wl,-rpath,/usr/local/openresty/pcre/lib:/usr/local/openresty/openssl/lib' \ + " + +LABEL resty_image_base="${RESTY_IMAGE_BASE}" +LABEL resty_image_tag="${RESTY_IMAGE_TAG}" +LABEL resty_version="${RESTY_VERSION}" +LABEL resty_openssl_version="${RESTY_OPENSSL_VERSION}" +LABEL resty_openssl_patch_version="${RESTY_OPENSSL_PATCH_VERSION}" +LABEL resty_openssl_url_base="${RESTY_OPENSSL_URL_BASE}" +LABEL resty_pcre_version="${RESTY_PCRE_VERSION}" +LABEL resty_pcre_build_options="${RESTY_PCRE_BUILD_OPTIONS}" +LABEL resty_pcre_sha256="${RESTY_PCRE_SHA256}" +LABEL resty_config_options="${RESTY_CONFIG_OPTIONS}" +LABEL resty_config_options_more="${RESTY_CONFIG_OPTIONS_MORE}" +LABEL resty_config_deps="${_RESTY_CONFIG_DEPS}" +LABEL resty_add_package_builddeps="${RESTY_ADD_PACKAGE_BUILDDEPS}" +LABEL resty_add_package_rundeps="${RESTY_ADD_PACKAGE_RUNDEPS}" +LABEL resty_eval_pre_configure="${RESTY_EVAL_PRE_CONFIGURE}" +LABEL resty_eval_post_make="${RESTY_EVAL_POST_MAKE}" +LABEL resty_luajit_options="${RESTY_LUAJIT_OPTIONS}" +LABEL resty_pcre_options="${RESTY_PCRE_OPTIONS}" + +RUN apk add --no-cache --virtual .build-deps \ + build-base \ + coreutils \ + curl \ + gd-dev \ + geoip-dev \ + libxslt-dev \ + linux-headers \ + make \ + perl-dev \ + readline-dev \ + zlib-dev \ + ${RESTY_ADD_PACKAGE_BUILDDEPS} \ + && apk add --no-cache \ + gd \ + geoip \ + libgcc \ + libxslt \ + zlib \ + ${RESTY_ADD_PACKAGE_RUNDEPS} \ + && cd /tmp \ + && if [ -n "${RESTY_EVAL_PRE_CONFIGURE}" ]; then eval $(echo ${RESTY_EVAL_PRE_CONFIGURE}); fi \ + && cd /tmp \ + && curl -fSL "${RESTY_OPENSSL_URL_BASE}/openssl-${RESTY_OPENSSL_VERSION}.tar.gz" -o openssl-${RESTY_OPENSSL_VERSION}.tar.gz \ + && tar xzf openssl-${RESTY_OPENSSL_VERSION}.tar.gz \ + && cd openssl-${RESTY_OPENSSL_VERSION} \ + && if [ $(echo ${RESTY_OPENSSL_VERSION} | cut -c 1-5) = "1.1.1" ] ; then \ + echo 'patching OpenSSL 1.1.1 for OpenResty' \ + && curl -s https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-${RESTY_OPENSSL_PATCH_VERSION}-sess_set_get_cb_yield.patch | patch -p1 ; \ + fi \ + && if [ $(echo ${RESTY_OPENSSL_VERSION} | cut -c 1-5) = "1.1.0" ] ; then \ + echo 'patching OpenSSL 1.1.0 for OpenResty' \ + && curl -s https://raw.githubusercontent.com/openresty/openresty/ed328977028c3ec3033bc25873ee360056e247cd/patches/openssl-1.1.0j-parallel_build_fix.patch | patch -p1 \ + && curl -s https://raw.githubusercontent.com/openresty/openresty/master/patches/openssl-${RESTY_OPENSSL_PATCH_VERSION}-sess_set_get_cb_yield.patch | patch -p1 ; \ + fi \ + && ./config \ + no-threads shared zlib -g \ + enable-ssl3 enable-ssl3-method \ + --prefix=/usr/local/openresty/openssl \ + --libdir=lib \ + -Wl,-rpath,/usr/local/openresty/openssl/lib \ + && make -j${RESTY_J} \ + && make -j${RESTY_J} install_sw \ + && cd /tmp \ + && curl -fSL https://downloads.sourceforge.net/project/pcre/pcre/${RESTY_PCRE_VERSION}/pcre-${RESTY_PCRE_VERSION}.tar.gz -o pcre-${RESTY_PCRE_VERSION}.tar.gz \ + && echo "${RESTY_PCRE_SHA256} pcre-${RESTY_PCRE_VERSION}.tar.gz" | shasum -a 256 --check \ + && tar xzf pcre-${RESTY_PCRE_VERSION}.tar.gz \ + && cd /tmp/pcre-${RESTY_PCRE_VERSION} \ + && ./configure \ + --prefix=/usr/local/openresty/pcre \ + --disable-cpp \ + --enable-utf \ + --enable-unicode-properties \ + ${RESTY_PCRE_BUILD_OPTIONS} \ + && make -j${RESTY_J} \ + && make -j${RESTY_J} install \ + && cd /tmp \ + && curl -fSL https://openresty.org/download/openresty-${RESTY_VERSION}.tar.gz -o openresty-${RESTY_VERSION}.tar.gz \ + && tar xzf openresty-${RESTY_VERSION}.tar.gz \ + && cd /tmp/openresty-${RESTY_VERSION} \ + && eval ./configure -j${RESTY_J} ${_RESTY_CONFIG_DEPS} ${RESTY_CONFIG_OPTIONS} ${RESTY_CONFIG_OPTIONS_MORE} ${RESTY_LUAJIT_OPTIONS} ${RESTY_PCRE_OPTIONS} \ + && make -j${RESTY_J} \ + && make -j${RESTY_J} install \ + && cd /tmp \ + && if [ -n "${RESTY_EVAL_POST_MAKE}" ]; then eval $(echo ${RESTY_EVAL_POST_MAKE}); fi \ + && rm -rf \ + openssl-${RESTY_OPENSSL_VERSION}.tar.gz openssl-${RESTY_OPENSSL_VERSION} \ + pcre-${RESTY_PCRE_VERSION}.tar.gz pcre-${RESTY_PCRE_VERSION} \ + openresty-${RESTY_VERSION}.tar.gz openresty-${RESTY_VERSION} \ + && apk del .build-deps \ + && mkdir -p /var/run/openresty \ + && ln -sf /dev/stdout /usr/local/openresty/nginx/logs/access.log \ + && ln -sf /dev/stderr /usr/local/openresty/nginx/logs/error.log + +# Add additional binaries into PATH for convenience +ENV PATH=$PATH:/usr/local/openresty/luajit/bin:/usr/local/openresty/nginx/sbin:/usr/local/openresty/bin + +# Copy nginx configuration files +COPY nginx.conf /usr/local/openresty/nginx/conf/nginx.conf +COPY nginx.vh.default.conf /etc/nginx/conf.d/default.conf + +CMD ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"] + +# Use SIGQUIT instead of default SIGTERM to cleanly drain requests +# See https://github.com/openresty/docker-openresty/blob/master/README.md#tips--pitfalls +STOPSIGNAL SIGQUIT -FROM openresty/openresty:buster +# Openreplay Custom configs +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main # Adding prometheus monitoring support ADD https://raw.githubusercontent.com/knyar/nginx-lua-prometheus/master/prometheus.lua /usr/local/openresty/lualib/ ADD https://raw.githubusercontent.com/knyar/nginx-lua-prometheus/master/prometheus_keys.lua /usr/local/openresty/lualib/ ADD https://raw.githubusercontent.com/knyar/nginx-lua-prometheus/master/prometheus_resty_counter.lua /usr/local/openresty/lualib/ -COPY --from=builder /work/lua-resty-balancer-master/*.so /usr/local/openresty/lualib/lua-resty-chash/ -COPY --from=builder /work/lua-resty-balancer-master/lib /usr/local/openresty/lualib/lua-resty-chash/lib/ - RUN chmod 0644 /usr/local/openresty/lualib/*.lua # Enabling monitoring on port 9145 diff --git a/scripts/dockerfiles/nginx/nginx.vh.default.conf b/scripts/dockerfiles/nginx/nginx.vh.default.conf new file mode 100644 index 000000000..3ad957225 --- /dev/null +++ b/scripts/dockerfiles/nginx/nginx.vh.default.conf @@ -0,0 +1,58 @@ +# nginx.vh.default.conf -- docker-openresty +# +# This file is installed to: +# `/etc/nginx/conf.d/default.conf` +# +# It tracks the `server` section of the upstream OpenResty's `nginx.conf`. +# +# This config (and any other configs in `etc/nginx/conf.d/`) is loaded by +# default by the `include` directive in `/usr/local/openresty/nginx/conf/nginx.conf`. +# +# See https://github.com/openresty/docker-openresty/blob/master/README.md#nginx-config-files +# + + +server { + listen 80; + server_name localhost; + + #charset koi8-r; + #access_log /var/log/nginx/host.access.log main; + + location / { + root /usr/local/openresty/nginx/html; + index index.html index.htm; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/local/openresty/nginx/html; + } + + # proxy the PHP scripts to Apache listening on 127.0.0.1:80 + # + #location ~ \.php$ { + # proxy_pass http://127.0.0.1; + #} + + # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 + # + #location ~ \.php$ { + # root /usr/local/openresty/nginx/html; + # fastcgi_pass 127.0.0.1:9000; + # fastcgi_index index.php; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; + # include fastcgi_params; + #} + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + #location ~ /\.ht { + # deny all; + #} +} From 901d90b26e409081d02f0f2ca91db71a950a22ea Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Wed, 20 Jul 2022 11:49:18 +0000 Subject: [PATCH 09/47] chore(docker): Updated docker base image Signed-off-by: rjshrjndrn --- api/Dockerfile | 1 + api/Dockerfile.alerts | 2 +- backend/Dockerfile | 1 + ee/api/Dockerfile | 3 ++- ee/api/Dockerfile.alerts | 2 +- ee/utilities/Dockerfile | 3 ++- frontend/Dockerfile | 1 + peers/Dockerfile | 3 ++- utilities/Dockerfile | 3 ++- 9 files changed, 13 insertions(+), 6 deletions(-) diff --git a/api/Dockerfile b/api/Dockerfile index b92e909e4..bbcf6f158 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -3,6 +3,7 @@ LABEL Maintainer="Rajesh Rajendran" LABEL Maintainer="KRAIEM Taha Yassine" RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache build-base nodejs npm tini +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main ARG envarg # Add Tini # Startup daemon diff --git a/api/Dockerfile.alerts b/api/Dockerfile.alerts index ca714db55..5830966b3 100644 --- a/api/Dockerfile.alerts +++ b/api/Dockerfile.alerts @@ -17,4 +17,4 @@ COPY . . RUN mv env.default .env && mv app_alerts.py app.py && mv entrypoint_alerts.sh entrypoint.sh ENTRYPOINT ["/sbin/tini", "--"] -CMD ./entrypoint.sh \ No newline at end of file +CMD ./entrypoint.sh diff --git a/backend/Dockerfile b/backend/Dockerfile index 3c3bebc3b..132fef1b0 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -19,6 +19,7 @@ RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o service -tags musl openrep FROM alpine AS entrypoint +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache ca-certificates ENV TZ=UTC \ diff --git a/ee/api/Dockerfile b/ee/api/Dockerfile index 4148d1e9c..383d65815 100644 --- a/ee/api/Dockerfile +++ b/ee/api/Dockerfile @@ -3,6 +3,7 @@ LABEL Maintainer="Rajesh Rajendran" LABEL Maintainer="KRAIEM Taha Yassine" RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache build-base libressl libffi-dev libressl-dev libxslt-dev libxml2-dev xmlsec-dev xmlsec nodejs npm tini +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main ARG envarg ENV SOURCE_MAP_VERSION=0.7.4 \ APP_NAME=chalice \ @@ -21,4 +22,4 @@ COPY . . RUN mv env.default .env && mv /work_tmp/node_modules sourcemap-reader/. ENTRYPOINT ["/sbin/tini", "--"] -CMD ./entrypoint.sh \ No newline at end of file +CMD ./entrypoint.sh diff --git a/ee/api/Dockerfile.alerts b/ee/api/Dockerfile.alerts index b557dc308..a3bee2a28 100644 --- a/ee/api/Dockerfile.alerts +++ b/ee/api/Dockerfile.alerts @@ -17,4 +17,4 @@ COPY . . RUN mv env.default .env && mv app_alerts.py app.py && mv entrypoint_alerts.sh entrypoint.sh ENTRYPOINT ["/sbin/tini", "--"] -CMD ./entrypoint.sh \ No newline at end of file +CMD ./entrypoint.sh diff --git a/ee/utilities/Dockerfile b/ee/utilities/Dockerfile index f3e605ccc..3c9d2f600 100644 --- a/ee/utilities/Dockerfile +++ b/ee/utilities/Dockerfile @@ -1,5 +1,6 @@ FROM node:18-alpine LABEL Maintainer="KRAIEM Taha Yassine" +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache tini git libc6-compat && ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2 ARG envarg ENV ENTERPRISE_BUILD=${envarg} \ @@ -12,4 +13,4 @@ COPY package-lock.json . RUN npm install COPY . . ENTRYPOINT ["/sbin/tini", "--"] -CMD npm start \ No newline at end of file +CMD npm start diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 198c03c7a..b87d5c172 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -14,5 +14,6 @@ COPY nginx.conf /etc/nginx/conf.d/default.conf # Default step in docker build FROM nginx:alpine LABEL maintainer=Rajesh +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main COPY --from=builder /work/public /var/www/openreplay COPY nginx.conf /etc/nginx/conf.d/default.conf diff --git a/peers/Dockerfile b/peers/Dockerfile index c95415177..98475f750 100644 --- a/peers/Dockerfile +++ b/peers/Dockerfile @@ -1,6 +1,7 @@ FROM node:18-alpine LABEL Maintainer="KRAIEM Taha Yassine" RUN apk add --no-cache tini +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main ARG envarg ENV ENTERPRISE_BUILD=${envarg} @@ -10,4 +11,4 @@ COPY package-lock.json . RUN npm install COPY . . ENTRYPOINT ["/sbin/tini", "--"] -CMD npm start \ No newline at end of file +CMD npm start diff --git a/utilities/Dockerfile b/utilities/Dockerfile index 7c3a66719..cb9d081f1 100644 --- a/utilities/Dockerfile +++ b/utilities/Dockerfile @@ -1,6 +1,7 @@ FROM node:18-alpine LABEL Maintainer="KRAIEM Taha Yassine" RUN apk add --no-cache tini +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main ARG envarg ENV ENTERPRISE_BUILD=${envarg} \ MAXMINDDB_FILE=/root/geoip.mmdb @@ -12,4 +13,4 @@ COPY package-lock.json . RUN npm install COPY . . ENTRYPOINT ["/sbin/tini", "--"] -CMD npm start \ No newline at end of file +CMD npm start From 1f2399d163c92e3d6d13d4729bd368ae097828ee Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Wed, 20 Jul 2022 14:25:16 +0200 Subject: [PATCH 10/47] feat(chalice): changed Dockerfile feat(alerts): changed Dockerfile feat(crons): changed Dockerfile --- api/Dockerfile | 1 - ee/api/Dockerfile | 1 - 2 files changed, 2 deletions(-) diff --git a/api/Dockerfile b/api/Dockerfile index bbcf6f158..b92e909e4 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -3,7 +3,6 @@ LABEL Maintainer="Rajesh Rajendran" LABEL Maintainer="KRAIEM Taha Yassine" RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache build-base nodejs npm tini -RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main ARG envarg # Add Tini # Startup daemon diff --git a/ee/api/Dockerfile b/ee/api/Dockerfile index 383d65815..1c5be7f36 100644 --- a/ee/api/Dockerfile +++ b/ee/api/Dockerfile @@ -3,7 +3,6 @@ LABEL Maintainer="Rajesh Rajendran" LABEL Maintainer="KRAIEM Taha Yassine" RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache build-base libressl libffi-dev libressl-dev libxslt-dev libxml2-dev xmlsec-dev xmlsec nodejs npm tini -RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main ARG envarg ENV SOURCE_MAP_VERSION=0.7.4 \ APP_NAME=chalice \ From b8f2931b3f5dc7bd7a33c98fb20f11d1a3cf31b7 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Wed, 20 Jul 2022 14:53:53 +0200 Subject: [PATCH 11/47] chore(docker): ingress-controller fix critical vulnerability Signed-off-by: rjshrjndrn --- scripts/dockerfiles/ingress-controller/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 scripts/dockerfiles/ingress-controller/Dockerfile diff --git a/scripts/dockerfiles/ingress-controller/Dockerfile b/scripts/dockerfiles/ingress-controller/Dockerfile new file mode 100644 index 000000000..595be9b4f --- /dev/null +++ b/scripts/dockerfiles/ingress-controller/Dockerfile @@ -0,0 +1,3 @@ +from k8s.gcr.io/ingress-nginx/controller +# Fix critical vulnerability +RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main From 7c0b1d7f3a40d007763e67ac4e1cc7ee036524c3 Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Wed, 20 Jul 2022 14:58:43 +0200 Subject: [PATCH 12/47] feat(crons): changed weekly report --- api/chalicelib/core/weekly_report.py | 18 +++++++++++++++++- ee/api/chalicelib/core/weekly_report.py | 18 +++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/api/chalicelib/core/weekly_report.py b/api/chalicelib/core/weekly_report.py index 952bf584b..afb0843ce 100644 --- a/api/chalicelib/core/weekly_report.py +++ b/api/chalicelib/core/weekly_report.py @@ -32,7 +32,8 @@ def cron(): if not helper.has_smtp(): print("!!! No SMTP configuration found, ignoring weekly report") return - with pg_client.PostgresClient(long_query=True) as cur: + _now = TimeUTC.now() + with pg_client.PostgresClient(unlimited_query=True) as cur: params = {"tomorrow": TimeUTC.midnight(delta_days=1), "3_days_ago": TimeUTC.midnight(delta_days=-3), "1_week_ago": TimeUTC.midnight(delta_days=-7), @@ -86,6 +87,9 @@ def cron(): AND issues.timestamp >= %(5_week_ago)s ) AS month_1_issues ON (TRUE);"""), params) projects_data = cur.fetchall() + _now2 = TimeUTC.now() + print(f">> Weekly report query: {_now2 - _now} ms") + _now = _now2 emails_to_send = [] for p in projects_data: params["project_id"] = p["project_id"] @@ -116,6 +120,9 @@ def cron(): ) AS timestamp_i ORDER BY timestamp_i;""", params)) days_partition = cur.fetchall() + _now2 = TimeUTC.now() + print(f">> Weekly report s-query-1: {_now2 - _now} ms project_id: {p['project_id']}") + _now = _now2 max_days_partition = max(x['issues_count'] for x in days_partition) for d in days_partition: if max_days_partition <= 0: @@ -132,6 +139,9 @@ def cron(): ORDER BY count DESC, type LIMIT 4;""", params)) issues_by_type = cur.fetchall() + _now2 = TimeUTC.now() + print(f">> Weekly report s-query-1: {_now2 - _now} ms project_id: {p['project_id']}") + _now = _now2 max_issues_by_type = sum(i["count"] for i in issues_by_type) for i in issues_by_type: i["type"] = get_issue_title(i["type"]) @@ -161,6 +171,9 @@ def cron(): GROUP BY timestamp_i ORDER BY timestamp_i;""", params)) issues_breakdown_by_day = cur.fetchall() + _now2 = TimeUTC.now() + print(f">> Weekly report s-query-1: {_now2 - _now} ms project_id: {p['project_id']}") + _now = _now2 for i in issues_breakdown_by_day: i["sum"] = sum(x["count"] for x in i["partition"]) for j in i["partition"]: @@ -207,6 +220,9 @@ def cron(): GROUP BY type ORDER BY issue_count DESC;""", params)) issues_breakdown_list = cur.fetchall() + _now2 = TimeUTC.now() + print(f">> Weekly report s-query-1: {_now2 - _now} ms project_id: {p['project_id']}") + _now = _now2 if len(issues_breakdown_list) > 4: others = {"type": "Others", "sessions_count": sum(i["sessions_count"] for i in issues_breakdown_list[4:]), diff --git a/ee/api/chalicelib/core/weekly_report.py b/ee/api/chalicelib/core/weekly_report.py index 90256d795..96bda859e 100644 --- a/ee/api/chalicelib/core/weekly_report.py +++ b/ee/api/chalicelib/core/weekly_report.py @@ -32,7 +32,8 @@ def cron(): if not helper.has_smtp(): print("!!! No SMTP configuration found, ignoring weekly report") return - with pg_client.PostgresClient(long_query=True) as cur: + _now = TimeUTC.now() + with pg_client.PostgresClient(unlimited_query=True) as cur: params = {"tomorrow": TimeUTC.midnight(delta_days=1), "3_days_ago": TimeUTC.midnight(delta_days=-3), "1_week_ago": TimeUTC.midnight(delta_days=-7), @@ -87,6 +88,9 @@ def cron(): AND issues.timestamp >= %(5_week_ago)s ) AS month_1_issues ON (TRUE);"""), params) projects_data = cur.fetchall() + _now2 = TimeUTC.now() + print(f">> Weekly report query: {_now2 - _now} ms") + _now = _now2 emails_to_send = [] for p in projects_data: params["project_id"] = p["project_id"] @@ -117,6 +121,9 @@ def cron(): ) AS timestamp_i ORDER BY timestamp_i;""", params)) days_partition = cur.fetchall() + _now2 = TimeUTC.now() + print(f">> Weekly report s-query-1: {_now2 - _now} ms project_id: {p['project_id']}") + _now = _now2 max_days_partition = max(x['issues_count'] for x in days_partition) for d in days_partition: if max_days_partition <= 0: @@ -133,6 +140,9 @@ def cron(): ORDER BY count DESC, type LIMIT 4;""", params)) issues_by_type = cur.fetchall() + _now2 = TimeUTC.now() + print(f">> Weekly report s-query-1: {_now2 - _now} ms project_id: {p['project_id']}") + _now = _now2 max_issues_by_type = sum(i["count"] for i in issues_by_type) for i in issues_by_type: i["type"] = get_issue_title(i["type"]) @@ -162,6 +172,9 @@ def cron(): GROUP BY timestamp_i ORDER BY timestamp_i;""", params)) issues_breakdown_by_day = cur.fetchall() + _now2 = TimeUTC.now() + print(f">> Weekly report s-query-1: {_now2 - _now} ms project_id: {p['project_id']}") + _now = _now2 for i in issues_breakdown_by_day: i["sum"] = sum(x["count"] for x in i["partition"]) for j in i["partition"]: @@ -208,6 +221,9 @@ def cron(): GROUP BY type ORDER BY issue_count DESC;""", params)) issues_breakdown_list = cur.fetchall() + _now2 = TimeUTC.now() + print(f">> Weekly report s-query-1: {_now2 - _now} ms project_id: {p['project_id']}") + _now = _now2 if len(issues_breakdown_list) > 4: others = {"type": "Others", "sessions_count": sum(i["sessions_count"] for i in issues_breakdown_list[4:]), From 6da35d58ebfdd963c515d95325ab17d98d5a1256 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Wed, 20 Jul 2022 14:53:53 +0200 Subject: [PATCH 13/47] chore(docker): ingress-controller fix critical vulnerability Signed-off-by: rjshrjndrn --- scripts/dockerfiles/ingress-controller/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/dockerfiles/ingress-controller/Dockerfile b/scripts/dockerfiles/ingress-controller/Dockerfile index 595be9b4f..85f58d272 100644 --- a/scripts/dockerfiles/ingress-controller/Dockerfile +++ b/scripts/dockerfiles/ingress-controller/Dockerfile @@ -1,3 +1,5 @@ -from k8s.gcr.io/ingress-nginx/controller +from k8s.gcr.io/ingress-nginx/controller:v1.3.0 # Fix critical vulnerability +user 0 RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main +user 101 From ab800a40d76cc77c3f7c02bead8f312cecc044d0 Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Wed, 20 Jul 2022 15:24:29 +0200 Subject: [PATCH 14/47] feat(chalice): changed env-vars handling feat(alerts): changed env-vars handling feat(crons): changed env-vars handling --- ee/api/entrypoint.sh | 2 +- ee/api/entrypoint_alerts.sh | 2 +- ee/api/entrypoint_crons.sh | 2 +- ee/api/env_vars.sh | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/ee/api/entrypoint.sh b/ee/api/entrypoint.sh index 60aba72a6..724c7d6f1 100755 --- a/ee/api/entrypoint.sh +++ b/ee/api/entrypoint.sh @@ -1,6 +1,6 @@ #!/bin/sh sh env_vars.sh -source .env.override +source /tmp/.env.override cd sourcemap-reader nohup npm start &> /tmp/sourcemap-reader.log & cd .. diff --git a/ee/api/entrypoint_alerts.sh b/ee/api/entrypoint_alerts.sh index d2e6d677b..04e60ce1b 100755 --- a/ee/api/entrypoint_alerts.sh +++ b/ee/api/entrypoint_alerts.sh @@ -1,4 +1,4 @@ #!/bin/sh sh env_vars.sh -source .env.override +source /tmp/.env.override uvicorn app:app --host 0.0.0.0 --reload diff --git a/ee/api/entrypoint_crons.sh b/ee/api/entrypoint_crons.sh index ef29496b2..b6c03bf75 100755 --- a/ee/api/entrypoint_crons.sh +++ b/ee/api/entrypoint_crons.sh @@ -1,4 +1,4 @@ #!/bin/sh sh env_vars.sh -source .env.override +source /tmp/.env.override python app_crons.py $ACTION diff --git a/ee/api/env_vars.sh b/ee/api/env_vars.sh index a17610aab..22db81961 100755 --- a/ee/api/env_vars.sh +++ b/ee/api/env_vars.sh @@ -1,12 +1,12 @@ #!/bin/sh -touch .env.override +touch /tmp/.env.override if [[ -z "${ENV_CONFIG_OVERRIDE_PATH}" ]]; then echo 'no env-override' else override=$ENV_CONFIG_OVERRIDE_PATH if [ -f "$override" ]; then - cp $override .env.override + cp $override /tmp/.env.override else echo "$override does not exist." fi From 591efd5a653b3257aa8926de4e4ae65e0365cfee Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Wed, 20 Jul 2022 17:18:04 +0000 Subject: [PATCH 15/47] chore(docker): Run non root users for containers Signed-off-by: rjshrjndrn --- api/Dockerfile | 3 +++ api/Dockerfile.alerts | 2 ++ api/Dockerfile.bundle | 2 ++ backend/Dockerfile | 2 ++ ee/api/Dockerfile | 3 +++ ee/api/Dockerfile.alerts | 3 +++ ee/api/Dockerfile.crons | 3 +++ ee/utilities/Dockerfile | 2 ++ frontend/Dockerfile | 8 ++++++++ peers/Dockerfile | 2 ++ scripts/helmcharts/init.sh | 8 ++++++-- scripts/helmcharts/openreplay/charts/sink/values.yaml | 6 +++++- scripts/helmcharts/openreplay/charts/storage/values.yaml | 6 +++++- utilities/Dockerfile | 2 ++ 14 files changed, 48 insertions(+), 4 deletions(-) diff --git a/api/Dockerfile b/api/Dockerfile index b92e909e4..0d949e25e 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -22,5 +22,8 @@ WORKDIR /work COPY . . RUN mv env.default .env && mv /work_tmp/node_modules sourcemap-reader/. +RUN adduser -u 1001 openreplay -D +USER 1001 + ENTRYPOINT ["/sbin/tini", "--"] CMD ./entrypoint.sh diff --git a/api/Dockerfile.alerts b/api/Dockerfile.alerts index 5830966b3..c4614b3c1 100644 --- a/api/Dockerfile.alerts +++ b/api/Dockerfile.alerts @@ -16,5 +16,7 @@ WORKDIR /work COPY . . RUN mv env.default .env && mv app_alerts.py app.py && mv entrypoint_alerts.sh entrypoint.sh +RUN adduser -u 1001 openreplay -D +USER 1001 ENTRYPOINT ["/sbin/tini", "--"] CMD ./entrypoint.sh diff --git a/api/Dockerfile.bundle b/api/Dockerfile.bundle index 2f58635f2..b047f6d6c 100644 --- a/api/Dockerfile.bundle +++ b/api/Dockerfile.bundle @@ -23,5 +23,7 @@ ARG envarg ENV ENTERPRISE_BUILD ${envarg} ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini RUN chmod +x /tini +RUN adduser -u 1001 openreplay -D +USER 1001 ENTRYPOINT ["/tini", "--"] CMD ./entrypoint.sh diff --git a/backend/Dockerfile b/backend/Dockerfile index 132fef1b0..648d82bea 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -69,4 +69,6 @@ RUN if [ "$SERVICE_NAME" = "http" ]; then \ COPY --from=build /root/service /root/service +RUN adduser -u 1001 openreplay -D +USER 1001 ENTRYPOINT /root/service diff --git a/ee/api/Dockerfile b/ee/api/Dockerfile index 1c5be7f36..2500d2bfb 100644 --- a/ee/api/Dockerfile +++ b/ee/api/Dockerfile @@ -20,5 +20,8 @@ WORKDIR /work COPY . . RUN mv env.default .env && mv /work_tmp/node_modules sourcemap-reader/. +RUN adduser -u 1001 openreplay -D +USER 1001 + ENTRYPOINT ["/sbin/tini", "--"] CMD ./entrypoint.sh diff --git a/ee/api/Dockerfile.alerts b/ee/api/Dockerfile.alerts index a3bee2a28..785b0a5f9 100644 --- a/ee/api/Dockerfile.alerts +++ b/ee/api/Dockerfile.alerts @@ -16,5 +16,8 @@ WORKDIR /work COPY . . RUN mv env.default .env && mv app_alerts.py app.py && mv entrypoint_alerts.sh entrypoint.sh +RUN adduser -u 1001 openreplay -D +USER 1001 + ENTRYPOINT ["/sbin/tini", "--"] CMD ./entrypoint.sh diff --git a/ee/api/Dockerfile.crons b/ee/api/Dockerfile.crons index e29b4440f..0647c6fc6 100644 --- a/ee/api/Dockerfile.crons +++ b/ee/api/Dockerfile.crons @@ -18,5 +18,8 @@ WORKDIR /work COPY . . RUN mv env.default .env && mv entrypoint_crons.sh entrypoint.sh +RUN adduser -u 1001 openreplay -D +USER 1001 + ENTRYPOINT ["/sbin/tini", "--"] CMD ./entrypoint.sh diff --git a/ee/utilities/Dockerfile b/ee/utilities/Dockerfile index 3c9d2f600..f01c7d71c 100644 --- a/ee/utilities/Dockerfile +++ b/ee/utilities/Dockerfile @@ -12,5 +12,7 @@ COPY package.json . COPY package-lock.json . RUN npm install COPY . . +RUN adduser -u 1001 openreplay -D +USER 1001 ENTRYPOINT ["/sbin/tini", "--"] CMD npm start diff --git a/frontend/Dockerfile b/frontend/Dockerfile index b87d5c172..2ab0312ab 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -17,3 +17,11 @@ LABEL maintainer=Rajesh RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main COPY --from=builder /work/public /var/www/openreplay COPY nginx.conf /etc/nginx/conf.d/default.conf + +RUN chown -R nginx:nginx /var/cache/nginx && \ + chown -R nginx:nginx /var/log/nginx && \ + chown -R nginx:nginx /etc/nginx/conf.d && \ + touch /var/run/nginx.pid && \ + chown -R nginx:nginx /var/run/nginx.pid + +USER nginx diff --git a/peers/Dockerfile b/peers/Dockerfile index 98475f750..b05fdee3a 100644 --- a/peers/Dockerfile +++ b/peers/Dockerfile @@ -10,5 +10,7 @@ COPY package.json . COPY package-lock.json . RUN npm install COPY . . +RUN adduser -u 1001 openreplay -D +USER 1001 ENTRYPOINT ["/sbin/tini", "--"] CMD npm start diff --git a/scripts/helmcharts/init.sh b/scripts/helmcharts/init.sh index 078a60583..5fe454f90 100644 --- a/scripts/helmcharts/init.sh +++ b/scripts/helmcharts/init.sh @@ -107,8 +107,12 @@ sed_i_wrapper -i "s/secretKey: \"changeMeMinioPassword\"/secretKey: \"$(randomPa sed_i_wrapper -i "s/jwt_secret: \"SetARandomStringHere\"/jwt_secret: \"$(randomPass)\"/g" vars.yaml sed_i_wrapper -i "s/domainName: \"\"/domainName: \"${DOMAIN_NAME}\"/g" vars.yaml +info "Setting proper permission for shared folder" +sudo mkdir -p /openreplay/storage/nfs +sudo chown -R 1001:1001 /openreplay/storage/nfs + ## Installing OpenReplay -info "Installing databases" +info "installing databases" helm upgrade --install databases ./databases -n db --create-namespace --wait -f ./vars.yaml --atomic -info "Installing application" +info "installing application" helm upgrade --install openreplay ./openreplay -n app --create-namespace --wait -f ./vars.yaml --atomic diff --git a/scripts/helmcharts/openreplay/charts/sink/values.yaml b/scripts/helmcharts/openreplay/charts/sink/values.yaml index 11df1d4e7..a37ecfa41 100644 --- a/scripts/helmcharts/openreplay/charts/sink/values.yaml +++ b/scripts/helmcharts/openreplay/charts/sink/values.yaml @@ -25,7 +25,11 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" # fsGroup: 2000 securityContext: {} diff --git a/scripts/helmcharts/openreplay/charts/storage/values.yaml b/scripts/helmcharts/openreplay/charts/storage/values.yaml index 5adbf189f..b73c2cf1e 100644 --- a/scripts/helmcharts/openreplay/charts/storage/values.yaml +++ b/scripts/helmcharts/openreplay/charts/storage/values.yaml @@ -25,7 +25,11 @@ serviceAccount: podAnnotations: {} -podSecurityContext: {} +podSecurityContext: + runAsUser: 1001 + runAsGroup: 1001 + fsGroup: 1001 + fsGroupChangePolicy: "OnRootMismatch" # fsGroup: 2000 securityContext: {} diff --git a/utilities/Dockerfile b/utilities/Dockerfile index cb9d081f1..cbf217339 100644 --- a/utilities/Dockerfile +++ b/utilities/Dockerfile @@ -12,5 +12,7 @@ COPY package.json . COPY package-lock.json . RUN npm install COPY . . +RUN adduser -u 1001 openreplay -D +USER 1001 ENTRYPOINT ["/sbin/tini", "--"] CMD npm start From ce048087e6f27d38d174bcb226809fb290a9d72f Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Thu, 21 Jul 2022 08:56:57 +0200 Subject: [PATCH 16/47] fix(helm): updated non-root path for backend services Signed-off-by: rjshrjndrn --- backend/Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/Dockerfile b/backend/Dockerfile index 648d82bea..4f060587d 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -21,12 +21,13 @@ RUN CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o service -tags musl openrep FROM alpine AS entrypoint RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache ca-certificates +RUN adduser -u 1001 openreplay -D ENV TZ=UTC \ FS_ULIMIT=1000 \ FS_DIR=/mnt/efs \ - MAXMINDDB_FILE=/root/geoip.mmdb \ - UAPARSER_FILE=/root/regexes.yaml \ + MAXMINDDB_FILE=/home/openreplay/geoip.mmdb \ + UAPARSER_FILE=/home/openreplay/regexes.yaml \ HTTP_PORT=80 \ KAFKA_USE_SSL=true \ KAFKA_MAX_POLL_INTERVAL_MS=400000 \ @@ -68,7 +69,6 @@ RUN if [ "$SERVICE_NAME" = "http" ]; then \ wget https://static.openreplay.com/geoip/GeoLite2-Country.mmdb -O "$MAXMINDDB_FILE"; fi -COPY --from=build /root/service /root/service -RUN adduser -u 1001 openreplay -D +COPY --from=build /root/service /home/openreplay/service USER 1001 -ENTRYPOINT /root/service +ENTRYPOINT /home/openreplay/service From ff03c02e6d546ec58e759f5dbb8e9bb28eed9084 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Thu, 21 Jul 2022 07:16:56 +0000 Subject: [PATCH 17/47] fix(chalice): user permission issue for geodb Signed-off-by: rjshrjndrn --- ee/utilities/Dockerfile | 8 +++++--- utilities/Dockerfile | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/ee/utilities/Dockerfile b/ee/utilities/Dockerfile index f01c7d71c..2de6197a2 100644 --- a/ee/utilities/Dockerfile +++ b/ee/utilities/Dockerfile @@ -2,17 +2,19 @@ FROM node:18-alpine LABEL Maintainer="KRAIEM Taha Yassine" RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main RUN apk add --no-cache tini git libc6-compat && ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2 + ARG envarg ENV ENTERPRISE_BUILD=${envarg} \ - MAXMINDDB_FILE=/root/geoip.mmdb - + MAXMINDDB_FILE=/home/openreplay/geoip.mmdb WORKDIR /work -ADD https://static.openreplay.com/geoip/GeoLite2-Country.mmdb $MAXMINDDB_FILE COPY package.json . COPY package-lock.json . RUN npm install COPY . . + RUN adduser -u 1001 openreplay -D USER 1001 +ADD --chown=1001 https://static.openreplay.com/geoip/GeoLite2-Country.mmdb $MAXMINDDB_FILE + ENTRYPOINT ["/sbin/tini", "--"] CMD npm start diff --git a/utilities/Dockerfile b/utilities/Dockerfile index cbf217339..2de6197a2 100644 --- a/utilities/Dockerfile +++ b/utilities/Dockerfile @@ -1,18 +1,20 @@ FROM node:18-alpine LABEL Maintainer="KRAIEM Taha Yassine" -RUN apk add --no-cache tini RUN apk upgrade busybox --no-cache --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main +RUN apk add --no-cache tini git libc6-compat && ln -s /lib/libc.musl-x86_64.so.1 /lib/ld-linux-x86-64.so.2 + ARG envarg ENV ENTERPRISE_BUILD=${envarg} \ - MAXMINDDB_FILE=/root/geoip.mmdb - + MAXMINDDB_FILE=/home/openreplay/geoip.mmdb WORKDIR /work -ADD https://static.openreplay.com/geoip/GeoLite2-Country.mmdb $MAXMINDDB_FILE COPY package.json . COPY package-lock.json . RUN npm install COPY . . + RUN adduser -u 1001 openreplay -D USER 1001 +ADD --chown=1001 https://static.openreplay.com/geoip/GeoLite2-Country.mmdb $MAXMINDDB_FILE + ENTRYPOINT ["/sbin/tini", "--"] CMD npm start From 57b813b3728c9ed222c2580f3ba1fa845be26485 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Thu, 21 Jul 2022 10:43:10 +0200 Subject: [PATCH 18/47] chore(docker): updater ingress image Signed-off-by: rjshrjndrn --- scripts/helmcharts/openreplay/values.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/helmcharts/openreplay/values.yaml b/scripts/helmcharts/openreplay/values.yaml index 92a932aad..20700a4f2 100644 --- a/scripts/helmcharts/openreplay/values.yaml +++ b/scripts/helmcharts/openreplay/values.yaml @@ -102,4 +102,5 @@ ingress-nginx: ## for backwards compatibility consider setting the full image url via the repository value below ## use *either* current default registry/image or repository format or installing chart by providing the values.yaml will fail ## repository: - tag: "v1.2.1" + tag: "v1.3.0" + digest: "" From 8897207baaefee6b7a3a6f1476761a3ee64dcd24 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Thu, 21 Jul 2022 11:55:44 +0200 Subject: [PATCH 19/47] fix(ui) - session list refresh --- .../app/components/BugFinder/SessionList/SessionList.js | 2 +- frontend/app/duck/search.js | 3 ++- frontend/app/duck/sessions.js | 7 +++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/app/components/BugFinder/SessionList/SessionList.js b/frontend/app/components/BugFinder/SessionList/SessionList.js index 46a200192..de9a718f1 100644 --- a/frontend/app/components/BugFinder/SessionList/SessionList.js +++ b/frontend/app/components/BugFinder/SessionList/SessionList.js @@ -10,7 +10,7 @@ import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; // const ALL = 'all'; const PER_PAGE = 10; -const AUTOREFRESH_INTERVAL = 3 * 60 * 1000; +const AUTOREFRESH_INTERVAL = 2 * 60 * 1000; var timeoutId; @connect(state => ({ diff --git a/frontend/app/duck/search.js b/frontend/app/duck/search.js index c49b00b26..71361da14 100644 --- a/frontend/app/duck/search.js +++ b/frontend/app/duck/search.js @@ -150,6 +150,7 @@ export const reduceThenFetchResource = filter.filters = filter.filters.map(filterMap); filter.limit = 10; filter.page = getState().getIn(['search', 'currentPage']); + const forceFetch = filter.filters.length === 0; // duration filter from local storage if (!filter.filters.find((f) => f.type === FilterKey.DURATION)) { @@ -172,7 +173,7 @@ export const reduceThenFetchResource = } } - return isRoute(ERRORS_ROUTE, window.location.pathname) ? dispatch(fetchErrorsList(filter)) : dispatch(fetchSessionList(filter)); + return isRoute(ERRORS_ROUTE, window.location.pathname) ? dispatch(fetchErrorsList(filter)) : dispatch(fetchSessionList(filter, forceFetch)); }; export const edit = reduceThenFetchResource((instance) => ({ diff --git a/frontend/app/duck/sessions.js b/frontend/app/duck/sessions.js index 0d40ae9e5..e4a4ff7bd 100644 --- a/frontend/app/duck/sessions.js +++ b/frontend/app/duck/sessions.js @@ -67,8 +67,8 @@ const reducer = (state = initialState, action = {}) => { switch (action.type) { case INIT: return state.set('current', Session(action.session)); - case FETCH_LIST.REQUEST: - return action.clear ? state.set('list', List()) : state; + // case FETCH_LIST.REQUEST: + // return action.clear ? state.set('list', List()) : state; case FETCH_ERROR_STACK.SUCCESS: return state.set('errorStack', List(action.data.trace).map(ErrorStack)).set('sourcemapUploaded', action.data.sourcemapUploaded); case FETCH_LIVE_LIST.SUCCESS: @@ -224,7 +224,7 @@ function init(session) { } export const fetchList = - (params = {}, clear = false, force = false) => + (params = {}, force = false) => (dispatch, getState) => { if (!force) { // compare with the last fetched filter const oldFilters = getSessionFilter(); @@ -237,7 +237,6 @@ export const fetchList = return dispatch({ types: FETCH_LIST.toArray(), call: (client) => client.post('/sessions/search2', params), - clear, params: cleanParams(params), }); }; From de1aa45728351e1163d4a184387e5d6e2a73a8da Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Thu, 21 Jul 2022 11:57:56 +0200 Subject: [PATCH 20/47] change(ui) - session list refresh frequency --- frontend/app/components/BugFinder/SessionList/SessionList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/BugFinder/SessionList/SessionList.js b/frontend/app/components/BugFinder/SessionList/SessionList.js index de9a718f1..a2901812b 100644 --- a/frontend/app/components/BugFinder/SessionList/SessionList.js +++ b/frontend/app/components/BugFinder/SessionList/SessionList.js @@ -10,7 +10,7 @@ import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG'; // const ALL = 'all'; const PER_PAGE = 10; -const AUTOREFRESH_INTERVAL = 2 * 60 * 1000; +const AUTOREFRESH_INTERVAL = 5 * 60 * 1000; var timeoutId; @connect(state => ({ From 44d9565fd92a8c2a669167d02be6880892bed061 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Thu, 21 Jul 2022 11:57:18 +0200 Subject: [PATCH 21/47] chore(helm): sink/storage default user root Signed-off-by: rjshrjndrn --- scripts/helmcharts/openreplay/values.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/scripts/helmcharts/openreplay/values.yaml b/scripts/helmcharts/openreplay/values.yaml index 20700a4f2..65b67c6bc 100644 --- a/scripts/helmcharts/openreplay/values.yaml +++ b/scripts/helmcharts/openreplay/values.yaml @@ -92,6 +92,20 @@ nginx-ingress: # Overrides the image tag whose default is the chart appVersion. tag: "buster" +# Running sink and storage as non root users, because of existing volume permission change will take time +sink: + podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + fsGroupChangePolicy: "OnRootMismatch" +storage: + podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + fsGroupChangePolicy: "OnRootMismatch" + ingress-nginx: enabled: true controller: From 76cc305e5a20062fc10d4fc02d3ba859feb7af99 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Thu, 21 Jul 2022 12:06:40 +0200 Subject: [PATCH 22/47] TODO: revert in 1.8.0 force run http as root, as v1.7.0 http listens in 80 Signed-off-by: rjshrjndrn --- scripts/helmcharts/openreplay/values.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/helmcharts/openreplay/values.yaml b/scripts/helmcharts/openreplay/values.yaml index 65b67c6bc..1652dedab 100644 --- a/scripts/helmcharts/openreplay/values.yaml +++ b/scripts/helmcharts/openreplay/values.yaml @@ -92,6 +92,13 @@ nginx-ingress: # Overrides the image tag whose default is the chart appVersion. tag: "buster" +# By default http listens to 80 port, and for v1.7.0 http listens in 80 +http: + podSecurityContext: + runAsUser: 0 + runAsGroup: 0 + fsGroup: 0 + fsGroupChangePolicy: "OnRootMismatch" # Running sink and storage as non root users, because of existing volume permission change will take time sink: podSecurityContext: From 3a636bda68eb901783d0f8520797b69ba70f2a77 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Thu, 21 Jul 2022 15:35:01 +0200 Subject: [PATCH 23/47] fix(ui) - click maps count and percentage, dropdown --- .../PageInsightsPanel/PageInsightsPanel.tsx | 178 +++++++++--------- .../components/SelectorCard/SelectorCard.tsx | 44 +++-- .../SelectorsList/SelectorsList.tsx | 41 ++-- .../StatedScreen/StatedScreen.ts | 4 +- 4 files changed, 133 insertions(+), 134 deletions(-) diff --git a/frontend/app/components/Session_/PageInsightsPanel/PageInsightsPanel.tsx b/frontend/app/components/Session_/PageInsightsPanel/PageInsightsPanel.tsx index cec3e1af2..03d74a247 100644 --- a/frontend/app/components/Session_/PageInsightsPanel/PageInsightsPanel.tsx +++ b/frontend/app/components/Session_/PageInsightsPanel/PageInsightsPanel.tsx @@ -1,6 +1,5 @@ import React, { useEffect, useState } from 'react'; -import { Dropdown, Loader, Icon } from 'UI'; -import DateRange from 'Shared/DateRange'; +import { Loader, Icon } from 'UI'; import { connect } from 'react-redux'; import { fetchInsights } from 'Duck/sessions'; import SelectorsList from './components/SelectorsList/SelectorsList'; @@ -11,100 +10,103 @@ import Period from 'Types/app/period'; const JUMP_OFFSET = 1000; interface Props { - filters: any - fetchInsights: (filters: Record) => void - urls: [] - insights: any - events: Array - urlOptions: Array - loading: boolean - host: string - setActiveTab: (tab: string) => void + filters: any; + fetchInsights: (filters: Record) => void; + urls: []; + insights: any; + events: Array; + urlOptions: Array; + loading: boolean; + host: string; + setActiveTab: (tab: string) => void; } -function PageInsightsPanel({ - filters, fetchInsights, events = [], insights, urlOptions, host, loading = true, setActiveTab -}: Props) { - const [insightsFilters, setInsightsFilters] = useState(filters) - const defaultValue = (urlOptions && urlOptions[0]) ? urlOptions[0].value : '' +function PageInsightsPanel({ filters, fetchInsights, events = [], insights, urlOptions, host, loading = true, setActiveTab }: Props) { + const [insightsFilters, setInsightsFilters] = useState(filters); + const defaultValue = urlOptions && urlOptions[0] ? urlOptions[0].value : ''; - const period = new Period({ - start: insightsFilters.startDate, - end: insightsFilters.endDate, - rangeName: insightsFilters.rangeValue - }); + const period = Period({ + start: insightsFilters.startDate, + end: insightsFilters.endDate, + rangeName: insightsFilters.rangeValue, + }); - const onDateChange = (e) => { - const { startDate, endDate, rangeValue } = e.toJSON(); - setInsightsFilters({ ...insightsFilters, startDate, endDate, rangeValue }) - } + const onDateChange = (e: any) => { + const { startDate, endDate, rangeValue } = e.toJSON(); + setInsightsFilters({ ...insightsFilters, startDate, endDate, rangeValue }); + }; - useEffect(() => { - markTargets(insights.toJS()); - return () => { - markTargets(null) - } - }, [insights]) + useEffect(() => { + markTargets(insights.toJS()); + return () => { + markTargets(null); + }; + }, [insights]); - useEffect(() => { - if (urlOptions && urlOptions[0]) { - const url = insightsFilters.url ? insightsFilters.url : host + urlOptions[0].value; - Player.pause(); - fetchInsights({ ...insightsFilters, url }) - } - }, [insightsFilters]) + useEffect(() => { + if (urlOptions && urlOptions[0]) { + const url = insightsFilters.url ? insightsFilters.url : host + urlOptions[0].value; + Player.pause(); + fetchInsights({ ...insightsFilters, url }); + } + }, [insightsFilters]); - const onPageSelect = ({ value }: { value: Array }) => { - const event = events.find(item => item.url === value) - Player.jump(event.time + JUMP_OFFSET) - setInsightsFilters({ ...insightsFilters, url: host + value }) - markTargets([]) - }; + const onPageSelect = ({ value }: any) => { + const event = events.find((item) => item.url === value.value); + Player.jump(event.time + JUMP_OFFSET); + setInsightsFilters({ ...insightsFilters, url: host + value.value }); + markTargets([]); + }; - return ( -
-
-
- Clicks - + return ( +
+
+
+ Clicks + +
+
{ + setActiveTab(''); + }} + className="ml-auto flex items-center justify-center bg-white cursor-pointer" + > + +
+
+
+
In Page
+ -
- - - -
- ) + ); } -export default connect(state => { - const events = state.getIn([ 'sessions', 'visitedEvents' ]) - return { - filters: state.getIn(['sessions', 'insightFilters']), - host: state.getIn([ 'sessions', 'host' ]), - insights: state.getIn([ 'sessions', 'insights' ]), - events: events, - urlOptions: events.map(({ url, host }: any) => ({ label: url, value: url, host })), - loading: state.getIn([ 'sessions', 'fetchInsightsRequest', 'loading' ]), - } -}, { fetchInsights })(PageInsightsPanel); +export default connect( + (state) => { + const events = state.getIn(['sessions', 'visitedEvents']); + return { + filters: state.getIn(['sessions', 'insightFilters']), + host: state.getIn(['sessions', 'host']), + insights: state.getIn(['sessions', 'insights']), + events: events, + urlOptions: events.map(({ url, host }: any) => ({ label: url, value: url, host })), + loading: state.getIn(['sessions', 'fetchInsightsRequest', 'loading']), + }; + }, + { fetchInsights } +)(PageInsightsPanel); diff --git a/frontend/app/components/Session_/PageInsightsPanel/components/SelectorCard/SelectorCard.tsx b/frontend/app/components/Session_/PageInsightsPanel/components/SelectorCard/SelectorCard.tsx index 9007b6684..9a3ecc210 100644 --- a/frontend/app/components/Session_/PageInsightsPanel/components/SelectorCard/SelectorCard.tsx +++ b/frontend/app/components/Session_/PageInsightsPanel/components/SelectorCard/SelectorCard.tsx @@ -1,30 +1,34 @@ -import React, { useState } from 'react' -import stl from './SelectorCard.module.css' +import React, { useState } from 'react'; +import stl from './SelectorCard.module.css'; import cn from 'classnames'; import type { MarkedTarget } from 'Player/MessageDistributor/StatedScreen/StatedScreen'; import { activeTarget } from 'Player'; import { Tooltip } from 'react-tippy'; interface Props { - index?: number, - target: MarkedTarget, - showContent: boolean + index?: number; + target: MarkedTarget; + showContent: boolean; } -export default function SelectorCard({ index = 1, target, showContent } : Props) { - return ( -
activeTarget(index)}> -
- {/* @ts-ignore */} -
{index + 1}
-
{target.selector}
-
- { showContent && ( -
-
{target.count} Clicks - {target.percent}%
-
TOTAL CLICKS
+export default function SelectorCard({ index = 1, target, showContent }: Props) { + return ( +
activeTarget(index)}> +
+ {/* @ts-ignore */} + +
{index + 1}
+
+
{target.selector}
+
+ {showContent && ( +
+
+ {target.count} Clicks - {target.percent}% +
+
TOTAL CLICKS
+
+ )}
- ) } -
- ) + ); } diff --git a/frontend/app/components/Session_/PageInsightsPanel/components/SelectorsList/SelectorsList.tsx b/frontend/app/components/Session_/PageInsightsPanel/components/SelectorsList/SelectorsList.tsx index aceefb3b7..86274baba 100644 --- a/frontend/app/components/Session_/PageInsightsPanel/components/SelectorsList/SelectorsList.tsx +++ b/frontend/app/components/Session_/PageInsightsPanel/components/SelectorsList/SelectorsList.tsx @@ -1,33 +1,26 @@ -import React, { useState } from 'react' -import { NoContent } from 'UI' +import React from 'react'; +import { NoContent } from 'UI'; import { connectPlayer } from 'Player/store'; import SelectorCard from '../SelectorCard/SelectorCard'; import type { MarkedTarget } from 'Player/MessageDistributor/StatedScreen/StatedScreen'; -import stl from './selectorList.module.css' +import stl from './selectorList.module.css'; interface Props { - targets: Array, - activeTargetIndex: number + targets: Array; + activeTargetIndex: number; } -function SelectorsList({ targets, activeTargetIndex }: Props) { - return ( - -
- { targets && targets.map((target, index) => ( - - ))} -
-
- ) +function SelectorsList({ targets, activeTargetIndex }: Props) { + return ( + +
+ {targets && targets.map((target, index) => )} +
+
+ ); } - -export default connectPlayer(state => ({ - targets: state.markedTargets, - activeTargetIndex: state.activeTargetIndex, -}))(SelectorsList) +export default connectPlayer((state: any) => ({ + targets: state.markedTargets, + activeTargetIndex: state.activeTargetIndex, +}))(SelectorsList); diff --git a/frontend/app/player/MessageDistributor/StatedScreen/StatedScreen.ts b/frontend/app/player/MessageDistributor/StatedScreen/StatedScreen.ts index 5b74d9a3f..177419f35 100644 --- a/frontend/app/player/MessageDistributor/StatedScreen/StatedScreen.ts +++ b/frontend/app/player/MessageDistributor/StatedScreen/StatedScreen.ts @@ -145,9 +145,9 @@ export default class StatedScreen extends Screen { ...s, el, index: index++, - percent: 0, + percent: Math.round((s.count * 100) / totalCount), boundingRect: this.calculateRelativeBoundingRect(el), - count: Math.round((s.count * 100) / totalCount) + count: s.count, }) }); From 5262bf16bf5bc0bf82cc04838b448fb1ed406929 Mon Sep 17 00:00:00 2001 From: sylenien Date: Thu, 21 Jul 2022 16:12:05 +0200 Subject: [PATCH 24/47] fix(ui): fix clickmap card items selectors --- .../MessageDistributor/StatedScreen/Screen/BaseScreen.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts b/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts index fc52660f5..81ced7774 100644 --- a/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts +++ b/frontend/app/player/MessageDistributor/StatedScreen/Screen/BaseScreen.ts @@ -138,7 +138,8 @@ export default abstract class BaseScreen { getElementBySelector(selector: string): Element | null { if (!selector) return null; try { - return this.document?.querySelector(selector) || null; + const safeSelector = selector.replace(/:/g, '\\\\3A ').replace(/\//g, '\\/'); + return this.document?.querySelector(safeSelector) || null; } catch (e) { console.error("Can not select element. ", e) return null @@ -186,4 +187,4 @@ export default abstract class BaseScreen { clean() { window.removeEventListener('resize', this.scale); } -} \ No newline at end of file +} From e17fde7f379dd2940522204b80a6487906ec5ab4 Mon Sep 17 00:00:00 2001 From: Delirium Date: Thu, 21 Jul 2022 17:28:28 +0300 Subject: [PATCH 25/47] fix(ui): fix timezone settings (#629) --- .../SessionList/SessionListHeader.js | 26 ++++++++++++++++--- .../SelectDateRange/SelectDateRange.tsx | 17 +++++++----- .../components/shared/SessionItem/Counter.tsx | 4 +-- frontend/app/types/app/period.js | 11 +++++++- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/frontend/app/components/BugFinder/SessionList/SessionListHeader.js b/frontend/app/components/BugFinder/SessionList/SessionListHeader.js index bf4bf8b55..5e2702639 100644 --- a/frontend/app/components/BugFinder/SessionList/SessionListHeader.js +++ b/frontend/app/components/BugFinder/SessionList/SessionListHeader.js @@ -4,7 +4,10 @@ import SortDropdown from '../Filters/SortDropdown'; import { numberWithCommas } from 'App/utils'; import SelectDateRange from 'Shared/SelectDateRange'; import { applyFilter } from 'Duck/search'; -import Period from 'Types/app/period'; +import Record from 'Types/app/period'; +import { useStore } from 'App/mstore'; +import { useObserver } from 'mobx-react-lite'; +import { moment } from 'App/dateRange'; const sortOptionsMap = { 'startTs-desc': 'Newest', @@ -15,13 +18,30 @@ const sortOptionsMap = { const sortOptions = Object.entries(sortOptionsMap).map(([value, label]) => ({ value, label })); function SessionListHeader({ activeTab, count, applyFilter, filter }) { + const { settingsStore } = useStore(); + + const label = useObserver(() => settingsStore.sessionSettings.timezone.label); + const getTimeZoneOffset = React.useCallback(() => { + return label.slice(-6); + }, [label]); + const { startDate, endDate, rangeValue } = filter; - const period = new Period({ start: startDate, end: endDate, rangeName: rangeValue }); + const period = new Record({ start: startDate, end: endDate, rangeName: rangeValue }); const onDateChange = (e) => { const dateValues = e.toJSON(); + dateValues.startDate = moment(dateValues.startDate).utcOffset(getTimeZoneOffset(), true).valueOf(); + dateValues.endDate = moment(dateValues.endDate).utcOffset(getTimeZoneOffset(), true).valueOf(); applyFilter(dateValues); }; + + React.useEffect(() => { + const dateValues = period.toJSON(); + dateValues.startDate = moment(dateValues.startDate).startOf('day').utcOffset(getTimeZoneOffset(), true).valueOf(); + dateValues.endDate = moment(dateValues.endDate).endOf('day').utcOffset(getTimeZoneOffset(), true).valueOf(); + applyFilter(dateValues); + }, [label]); + return (
@@ -32,7 +52,7 @@ function SessionListHeader({ activeTab, count, applyFilter, filter }) { {
Sessions Captured in - +
}
diff --git a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx index 12b6ba016..da8a940a5 100644 --- a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx +++ b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx @@ -6,17 +6,19 @@ import { components } from 'react-select'; import DateRangePopup from 'Shared/DateRangeDropdown/DateRangePopup'; import OutsideClickDetectingDiv from 'Shared/OutsideClickDetectingDiv'; import cn from 'classnames'; +import { observer } from 'mobx-react-lite'; interface Props { period: any; onChange: (data: any) => void; disableCustom?: boolean; right?: boolean; + timezone?: string; [x: string]: any; } function SelectDateRange(props: Props) { const [isCustom, setIsCustom] = React.useState(false); - const { right = false, period, disableCustom = false, ...rest } = props; + const { right = false, period, disableCustom = false, timezone, ...rest } = props; let selectedValue = DATE_RANGE_OPTIONS.find((obj: any) => obj.value === period.rangeName); const options = DATE_RANGE_OPTIONS.filter((obj: any) => (disableCustom ? obj.value !== CUSTOM_RANGE : true)); @@ -24,15 +26,20 @@ function SelectDateRange(props: Props) { if (value === CUSTOM_RANGE) { setIsCustom(true); } else { + // @ts-ignore props.onChange(new Period({ rangeName: value })); } }; const onApplyDateRange = (value: any) => { - props.onChange(new Period({ rangeName: CUSTOM_RANGE, start: value.start, end: value.end })); + // @ts-ignore + const range = new Period({ rangeName: CUSTOM_RANGE, start: value.start, end: value.end }) + props.onChange(range); setIsCustom(false); }; + const isCustomRange = period.rangeName === CUSTOM_RANGE; + const customRange = isCustomRange ? period.rangeFormatted(undefined, timezone) : ''; return (
; + } + }; - const renderFiled = () => { - switch(filter.sourceType) { - case FilterType.NUMBER: - return ( - - ) - } - } - - return ( -
- { renderFiled()} -
- ); + return
{renderFiled()}
; } -export default FilterSource; \ No newline at end of file +export default FilterSource; From b5f65cf6e62e214178f8395e98a8d2eaee10c9ad Mon Sep 17 00:00:00 2001 From: Delirium Date: Thu, 21 Jul 2022 19:35:50 +0300 Subject: [PATCH 33/47] fix(ui): set default timezone as local tz in option select (#633) --- .../components/DefaultTimezone.tsx | 28 +------ frontend/app/mstore/types/sessionSettings.ts | 74 +++++++++++++------ 2 files changed, 53 insertions(+), 49 deletions(-) diff --git a/frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx b/frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx index 5ee40a489..dc14f6245 100644 --- a/frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx +++ b/frontend/app/components/shared/SessionSettings/components/DefaultTimezone.tsx @@ -8,36 +8,10 @@ import { toast } from 'react-toastify'; type TimezonesDropdown = Timezone[] -const generateGMTZones = (): TimezonesDropdown => { - const timezones: TimezonesDropdown = [] - - const positiveNumbers = [...Array(12).keys()]; - const negativeNumbers = [...Array(12).keys()].reverse(); - negativeNumbers.pop(); // remove trailing zero since we have one in positive numbers array - - const combinedArray = [...negativeNumbers, ...positiveNumbers]; - - for (let i = 0; i < combinedArray.length; i++) { - let symbol = i < 11 ? '-' : '+'; - let isUTC = i === 11 - let prefix = isUTC ? 'UTC / GMT' : 'GMT'; - let value = String(combinedArray[i]).padStart(2, '0'); - - let tz = `${prefix} ${symbol}${String(combinedArray[i]).padStart(2, '0')}:00` - - let dropdownValue = `UTC${symbol}${value}` - timezones.push({ label: tz, value: isUTC ? 'UTC' : dropdownValue }) - } - - timezones.splice(17, 0, { label: 'GMT +05:30', value: 'UTC+05:30' }) - return timezones -} - -const timezoneOptions: TimezonesDropdown = [...generateGMTZones()] - function DefaultTimezone() { const [changed, setChanged] = React.useState(false); const { settingsStore } = useStore(); + const timezoneOptions: TimezonesDropdown = settingsStore.sessionSettings.defaultTimezones; const [timezone, setTimezone] = React.useState(settingsStore.sessionSettings.timezone); const sessionSettings = useObserver(() => settingsStore.sessionSettings); diff --git a/frontend/app/mstore/types/sessionSettings.ts b/frontend/app/mstore/types/sessionSettings.ts index 47ed12917..493edd523 100644 --- a/frontend/app/mstore/types/sessionSettings.ts +++ b/frontend/app/mstore/types/sessionSettings.ts @@ -1,24 +1,54 @@ -import { makeAutoObservable, runInAction, action } from "mobx" -import { SKIP_TO_ISSUE, TIMEZONE, DURATION_FILTER } from 'App/constants/storageKeys' +import { makeAutoObservable, runInAction, action } from 'mobx'; +import moment from 'moment'; +import { SKIP_TO_ISSUE, TIMEZONE, DURATION_FILTER } from 'App/constants/storageKeys'; export type Timezone = { - label: string, - value: string, - } + label: string; + value: string; +}; + +export const generateGMTZones = (): Timezone[] => { + const timezones: Timezone[] = []; + + const positiveNumbers = [...Array(12).keys()]; + const negativeNumbers = [...Array(12).keys()].reverse(); + negativeNumbers.pop(); // remove trailing zero since we have one in positive numbers array + + const combinedArray = [...negativeNumbers, ...positiveNumbers]; + + for (let i = 0; i < combinedArray.length; i++) { + let symbol = i < 11 ? '-' : '+'; + let isUTC = i === 11; + let prefix = isUTC ? 'UTC / GMT' : 'GMT'; + let value = String(combinedArray[i]).padStart(2, '0'); + + let tz = `${prefix} ${symbol}${String(combinedArray[i]).padStart(2, '0')}:00`; + + let dropdownValue = `UTC${symbol}${value}`; + timezones.push({ label: tz, value: isUTC ? 'UTC' : dropdownValue }); + } + + timezones.splice(17, 0, { label: 'GMT +05:30', value: 'UTC+05:30' }); + return timezones; +}; export default class SessionSettings { + defaultTimezones = [...generateGMTZones()] skipToIssue: boolean = localStorage.getItem(SKIP_TO_ISSUE) === 'true'; timezone: Timezone; durationFilter: any = JSON.parse(localStorage.getItem(DURATION_FILTER) || '{}'); - captureRate: string = '0' - captureAll: boolean = false + captureRate: string = '0'; + captureAll: boolean = false; constructor() { // compatibility fix for old timezone storage // TODO: remove after a while (1.7.1?) - this.timezoneFix() - this.timezone = JSON.parse(localStorage.getItem(TIMEZONE)) || { label: 'UTC / GMT +00:00', value: 'UTC' } - makeAutoObservable(this) + const userTimezoneOffset = moment().format('Z'); + const defaultTimezone = this.defaultTimezones.find(tz => tz.value.includes('UTC' + userTimezoneOffset.slice(0,3))) || { label: 'Local', value: `UTC${userTimezoneOffset}` }; + + this.timezoneFix(defaultTimezone); + this.timezone = JSON.parse(localStorage.getItem(TIMEZONE)) || defaultTimezone; + makeAutoObservable(this); } merge = (settings: any) => { @@ -27,35 +57,35 @@ export default class SessionSettings { this.updateKey(key, settings[key]); } } - } + }; changeCaptureRate = (rate: string) => { - if (!rate) return this.captureRate = '0'; + if (!rate) return (this.captureRate = '0'); // react do no see the difference between 01 and 1 decimals, this is why we have to use string casting if (parseInt(rate, 10) <= 100) this.captureRate = `${parseInt(rate, 10)}`; - } + }; changeCaptureAll = (all: boolean) => { this.captureAll = all; - } + }; - timezoneFix() { - if (localStorage.getItem(TIMEZONE) === '[object Object]') { - localStorage.setItem(TIMEZONE, JSON.stringify({ label: 'UTC / GMT +00:00', value: 'UTC' })); + timezoneFix(defaultTimezone: Record) { + if (localStorage.getItem(TIMEZONE) === '[object Object]' || !localStorage.getItem(TIMEZONE)) { + localStorage.setItem(TIMEZONE, JSON.stringify(defaultTimezone)); } } - + updateKey = (key: string, value: any) => { runInAction(() => { - this[key] = value - }) + this[key] = value; + }); - if (key === 'captureRate' || key === 'captureAll') return + if (key === 'captureRate' || key === 'captureAll') return; if (key === 'durationFilter' || key === 'timezone') { localStorage.setItem(`__$session-${key}$__`, JSON.stringify(value)); } else { localStorage.setItem(`__$session-${key}$__`, value); } - } + }; } From 4654dccd29e3e1b7dcb0bf4c7ae5b7782990e0b9 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Thu, 21 Jul 2022 19:04:34 +0200 Subject: [PATCH 34/47] chore(helm): override the pvc name --- .../charts/utilities/templates/efs-cron.yaml | 6 +++--- .../openreplay/charts/utilities/values.yaml | 16 +++++++--------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml b/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml index b74b0cbad..a960ebea4 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml @@ -32,17 +32,17 @@ spec: - mountPath: /mnt/efs name: datadir restartPolicy: Never - {{- if eq .Values.pvc.name "hostPath" }} + {{- if eq .Values.efsCleaner.pvc.name "hostPath" }} volumes: - name: datadir hostPath: # Ensure the file directory is created. - path: {{ .Values.pvc.hostMountPath }} + path: {{ .Values.efsCleaner.pvc.hostMountPath }} type: DirectoryOrCreate {{- else }} volumes: - name: datadir persistentVolumeClaim: - claimName: {{ .Values.pvc.name }} + claimName: {{ .Values.efsCleaner.pvc.name }} {{- end }} diff --git a/scripts/helmcharts/openreplay/charts/utilities/values.yaml b/scripts/helmcharts/openreplay/charts/utilities/values.yaml index 17caeb5b5..49838d774 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/values.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/values.yaml @@ -9,8 +9,13 @@ efsCleaner: repository: "{{ .Values.global.openReplayContainerRegistry }}/alpine" pullPolicy: Always tag: 3.16.1 - # Overrides the image tag whose default is the chart appVersion. - tag: "" + pvc: + # This can be either persistentVolumeClaim or hostPath. + # In case of pvc, you'll have to provide the pvc name. + # For example + # name: openreplay-efs + name: hostPath + hostMountPath: /openreplay/storage/nfs telemetry: # https://crontab.guru/#5_12_*_*_* @@ -78,10 +83,3 @@ fullnameOverride: "utilities-openreplay" # refer: https://crontab.guru/#5_3_*_*_1 cron: "5 3 * * 1" -pvc: - # This can be either persistentVolumeClaim or hostPath. - # In case of pvc, you'll have to provide the pvc name. - # For example - # name: openreplay-efs - name: hostPath - hostMountPath: /openreplay/storage/nfs From 4f5c16896695368882e66da2373648d0a5e1d8a6 Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Thu, 21 Jul 2022 19:17:12 +0200 Subject: [PATCH 35/47] chore(helm): change job backoff policy Signed-off-by: rjshrjndrn --- .../openreplay/charts/utilities/templates/efs-cron.yaml | 2 ++ .../openreplay/charts/utilities/templates/report-cron.yaml | 1 + .../charts/utilities/templates/sessions-cleaner-cron.yaml | 1 + .../openreplay/charts/utilities/templates/telemetry-cron.yaml | 1 + 4 files changed, 5 insertions(+) diff --git a/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml b/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml index a960ebea4..d27a678da 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml @@ -9,8 +9,10 @@ spec: successfulJobsHistoryLimit: 1 jobTemplate: spec: + backoffLimit: 0 # Don't restart the failed jobs template: spec: + restartPolicy: Never containers: - name: efs-cleaner image: alpine diff --git a/scripts/helmcharts/openreplay/charts/utilities/templates/report-cron.yaml b/scripts/helmcharts/openreplay/charts/utilities/templates/report-cron.yaml index 350de8c12..678c15111 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/templates/report-cron.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/templates/report-cron.yaml @@ -10,6 +10,7 @@ spec: successfulJobsHistoryLimit: 1 jobTemplate: spec: + backoffLimit: 0 # Don't restart the failed jobs template: spec: restartPolicy: Never diff --git a/scripts/helmcharts/openreplay/charts/utilities/templates/sessions-cleaner-cron.yaml b/scripts/helmcharts/openreplay/charts/utilities/templates/sessions-cleaner-cron.yaml index 47246a5bd..2d625e97f 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/templates/sessions-cleaner-cron.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/templates/sessions-cleaner-cron.yaml @@ -10,6 +10,7 @@ spec: successfulJobsHistoryLimit: 1 jobTemplate: spec: + backoffLimit: 0 # Don't restart the failed jobs template: spec: restartPolicy: Never diff --git a/scripts/helmcharts/openreplay/charts/utilities/templates/telemetry-cron.yaml b/scripts/helmcharts/openreplay/charts/utilities/templates/telemetry-cron.yaml index 74d24b624..57de6ce90 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/templates/telemetry-cron.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/templates/telemetry-cron.yaml @@ -10,6 +10,7 @@ spec: successfulJobsHistoryLimit: 1 jobTemplate: spec: + backoffLimit: 0 # Don't restart the failed jobs template: spec: restartPolicy: Never From 8e52ee610d12732d837ec0f10991298e8c9204a8 Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Thu, 21 Jul 2022 20:19:29 +0200 Subject: [PATCH 36/47] feat(chalice): changed pg helper feat(crons): changed pg helper feat(alerts): changed pg helper --- api/chalicelib/utils/pg_client.py | 8 +++++--- api/routers/core.py | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/api/chalicelib/utils/pg_client.py b/api/chalicelib/utils/pg_client.py index 2abc9f6c7..eda7747f8 100644 --- a/api/chalicelib/utils/pg_client.py +++ b/api/chalicelib/utils/pg_client.py @@ -75,9 +75,11 @@ class PostgresClient: connection = None cursor = None long_query = False + unlimited_query = False def __init__(self, long_query=False, unlimited_query=False): self.long_query = long_query + self.unlimited_query = unlimited_query if unlimited_query: long_config = dict(_PG_CONFIG) long_config["application_name"] += "-UNLIMITED" @@ -85,7 +87,7 @@ class PostgresClient: elif long_query: long_config = dict(_PG_CONFIG) long_config["application_name"] += "-LONG" - long_config["options"] = f"-c statement_timeout={config('pg_long_timeout', cast=int, default=5*60) * 1000}" + long_config["options"] = f"-c statement_timeout={config('pg_long_timeout', cast=int, default=5 * 60) * 1000}" self.connection = psycopg2.connect(**long_config) else: self.connection = postgreSQL_pool.getconn() @@ -99,11 +101,11 @@ class PostgresClient: try: self.connection.commit() self.cursor.close() - if self.long_query: + if self.long_query or self.unlimited_query: self.connection.close() except Exception as error: print("Error while committing/closing PG-connection", error) - if str(error) == "connection already closed": + if str(error) == "connection already closed" and not self.long_query and not self.unlimited_query: print("Recreating the connexion pool") make_pool() else: diff --git a/api/routers/core.py b/api/routers/core.py index df98c1c09..2c3ff5b90 100644 --- a/api/routers/core.py +++ b/api/routers/core.py @@ -1171,4 +1171,5 @@ def get_limits(context: schemas.CurrentContext = Depends(OR_context)): @public_app.put('/', tags=["health"]) @public_app.delete('/', tags=["health"]) def health_check(): - return {"data": f"live {config('version_number', default='')}"} + return {"data": {"stage": f"live {config('version_number', default='')}", + "internalCrons": config("LOCAL_CRONS", default=False, cast=bool)}} From 4355829e16e45fe3c75830bd8899ccce9a05d85f Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Fri, 22 Jul 2022 10:35:56 +0200 Subject: [PATCH 37/47] chore(helm): efs cleaner enable verbose output Signed-off-by: rjshrjndrn --- .../openreplay/charts/utilities/templates/efs-cron.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml b/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml index d27a678da..233025bf2 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/templates/efs-cron.yaml @@ -23,6 +23,7 @@ spec: args: - | # Delete all the files older than 7 days + set -x echo "Cleaning NFS strorage for data older than 7 days" storage=`du -sh /mnt/efs` find /mnt/efs -type f -mtime +7 -delete From f038cf1dea3cdb089955b2e79d3d26f651521160 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Fri, 22 Jul 2022 15:11:11 +0200 Subject: [PATCH 38/47] change(ui) - performance filters show unit --- .../shared/Filters/FilterItem/FilterItem.tsx | 18 +++++++++--------- .../FilterSource/FilterSource.module.css | 2 +- .../Filters/FilterSource/FilterSource.tsx | 12 +++++++++--- .../shared/Filters/FilterValue/FilterValue.tsx | 4 +++- frontend/app/types/filter/newFilter.js | 11 ++++++----- 5 files changed, 28 insertions(+), 19 deletions(-) diff --git a/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx b/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx index 154e862a7..3d82dae7c 100644 --- a/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx +++ b/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx @@ -10,7 +10,7 @@ import SubFilterItem from '../SubFilterItem'; interface Props { filterIndex: number; filter: any; // event/filter - onUpdate: (filter) => void; + onUpdate: (filter: any) => void; onRemoveFilter: () => void; isFilter?: boolean; saveRequestPayloads?: boolean; @@ -20,26 +20,26 @@ function FilterItem(props: Props) { const canShowValues = !(filter.operator === 'isAny' || filter.operator === 'onAny' || filter.operator === 'isUndefined'); const isSubFilter = filter.type === FilterType.SUB_FILTERS; - const replaceFilter = (filter) => { + const replaceFilter = (filter: any) => { props.onUpdate({ ...filter, value: [''], - filters: filter.filters ? filter.filters.map((i) => ({ ...i, value: [''] })) : [], + filters: filter.filters ? filter.filters.map((i: any) => ({ ...i, value: [''] })) : [], }); }; - const onOperatorChange = (e, { name, value }) => { + const onOperatorChange = (e: any, { name, value }: any) => { props.onUpdate({ ...filter, operator: value.value }); }; - const onSourceOperatorChange = (e, { name, value }) => { + const onSourceOperatorChange = (e: any, { name, value }: any) => { props.onUpdate({ ...filter, sourceOperator: value.value }); }; - const onUpdateSubFilter = (subFilter, subFilterIndex) => { + const onUpdateSubFilter = (subFilter: any, subFilterIndex: any) => { props.onUpdate({ ...filter, - filters: filter.filters.map((i, index) => { + filters: filter.filters.map((i: any, index: any) => { if (index === subFilterIndex) { return subFilter; } @@ -90,8 +90,8 @@ function FilterItem(props: Props) { {isSubFilter && (
{filter.filters - .filter((i) => (i.key !== FilterKey.FETCH_REQUEST_BODY && i.key !== FilterKey.FETCH_RESPONSE_BODY) || saveRequestPayloads) - .map((subFilter, subFilterIndex) => ( + .filter((i: any) => (i.key !== FilterKey.FETCH_REQUEST_BODY && i.key !== FilterKey.FETCH_RESPONSE_BODY) || saveRequestPayloads) + .map((subFilter: any, subFilterIndex: any) => ( void; + onUpdate: (filter: any) => void; } function FilterSource(props: Props) { const { filter } = props; const [value, setValue] = useState(filter.source[0] || ''); - const debounceUpdate: any = React.useCallback(debounce(props.onUpdate, 1000), []); + const debounceUpdate: any = React.useCallback(debounce(props.onUpdate, 1000), [props.onUpdate]); useEffect(() => { setValue(filter.source[0] || ''); @@ -25,7 +26,12 @@ function FilterSource(props: Props) { const renderFiled = () => { switch (filter.sourceType) { case FilterType.NUMBER: - return ; + return ( +
+ +
{filter.sourceUnit}
+
+ ); } }; diff --git a/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx b/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx index 29dce323d..5638f9a1d 100644 --- a/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx +++ b/frontend/app/components/shared/Filters/FilterValue/FilterValue.tsx @@ -6,6 +6,7 @@ import FilterValueDropdown from '../FilterValueDropdown'; import FilterDuration from '../FilterDuration'; import { debounce } from 'App/utils'; import { assist as assistRoute, isRoute } from 'App/routes'; +import cn from 'classnames'; const ASSIST_ROUTE = assistRoute(); @@ -172,7 +173,8 @@ function FilterValue(props: Props) { }; return ( -
+ // +
{filter.type === FilterType.DURATION ? renderValueFiled(filter.value, 0) : filter.value && diff --git a/frontend/app/types/filter/newFilter.js b/frontend/app/types/filter/newFilter.js index 9034eba6f..9a87da2c6 100644 --- a/frontend/app/types/filter/newFilter.js +++ b/frontend/app/types/filter/newFilter.js @@ -44,11 +44,11 @@ export const filters = [ { key: FilterKey.USERANONYMOUSID, type: FilterType.MULTIPLE, category: FilterCategory.USER, label: 'User AnonymousId', operator: 'is', operatorOptions: filterOptions.stringOperators, icon: 'filters/userid' }, // PERFORMANCE - { key: FilterKey.DOM_COMPLETE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'DOM Complete', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/dom-complete', isEvent: true, hasSource: true, sourceOperator: '>=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, - { key: FilterKey.LARGEST_CONTENTFUL_PAINT_TIME, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Largest Contentful Paint', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/lcpt', isEvent: true, hasSource: true, sourceOperator: '>=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, - { key: FilterKey.TTFB, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Time to First Byte', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/ttfb', isEvent: true, hasSource: true, sourceOperator: '>=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, - { key: FilterKey.AVG_CPU_LOAD, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg CPU Load', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/cpu-load', isEvent: true, hasSource: true, sourceOperator: '>=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, - { key: FilterKey.AVG_MEMORY_USAGE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg Memory Usage', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/memory-load', isEvent: true, hasSource: true, sourceOperator: '>=', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, + { key: FilterKey.DOM_COMPLETE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'DOM Complete', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/dom-complete', isEvent: true, hasSource: true, sourceOperator: '>=', sourceUnit: 'ms', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, + { key: FilterKey.LARGEST_CONTENTFUL_PAINT_TIME, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Largest Contentful Paint', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/lcpt', isEvent: true, hasSource: true, sourceOperator: '>=', sourceUnit: 'ms', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, + { key: FilterKey.TTFB, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Time to First Byte', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/ttfb', isEvent: true, hasSource: true, sourceOperator: '>=', sourceUnit: 'ms', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, + { key: FilterKey.AVG_CPU_LOAD, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg CPU Load', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/cpu-load', isEvent: true, hasSource: true, sourceOperator: '>=', sourceUnit: '%', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, + { key: FilterKey.AVG_MEMORY_USAGE, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Avg Memory Usage', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, source: [], icon: 'filters/memory-load', isEvent: true, hasSource: true, sourceOperator: '>=', sourceUnit: 'mb', sourceType: FilterType.NUMBER, sourceOperatorOptions: filterOptions.customOperators }, { key: FilterKey.FETCH_FAILED, type: FilterType.MULTIPLE, category: FilterCategory.PERFORMANCE, label: 'Failed Request', operator: 'isAny', operatorOptions: filterOptions.stringOperatorsPerformance, icon: 'filters/fetch-failed', isEvent: true }, { key: FilterKey.ISSUE, type: FilterType.ISSUE, category: FilterCategory.JAVASCRIPT, label: 'Issue', operator: 'is', operatorOptions: filterOptions.getOperatorsByKeys(['is', 'isAny', 'isNot']), icon: 'filters/click', options: filterOptions.issueOptions }, ]; @@ -142,6 +142,7 @@ export default Record({ source: [""], sourceType: '', sourceOperator: '=', + sourceUnit: '', sourceOperatorOptions: [], operator: '', From 7d419225a0ffb580f5f04126f92db89ed00071ab Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Fri, 22 Jul 2022 16:30:34 +0200 Subject: [PATCH 39/47] feat(chalice): changed configuration feat(crons): changed configuration feat(alerts): changed configuration --- api/app.py | 2 +- api/app_alerts.py | 2 +- ee/api/app.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/app.py b/api/app.py index 959f1ef8f..4fd042d1a 100644 --- a/api/app.py +++ b/api/app.py @@ -13,7 +13,7 @@ from routers.crons import core_crons from routers.crons import core_dynamic_crons from routers.subs import dashboard, insights, metrics, v1_api -app = FastAPI(root_path="/api") +app = FastAPI(root_path="/api", docs_url=config("docs_url", default=""), redoc_url=config("redoc_url", default="")) @app.middleware('http') diff --git a/api/app_alerts.py b/api/app_alerts.py index 57bfcd55d..4e05ab1a8 100644 --- a/api/app_alerts.py +++ b/api/app_alerts.py @@ -6,7 +6,7 @@ from fastapi import FastAPI from chalicelib.core import alerts_processor -app = FastAPI() +app = FastAPI(root_path="/alerts", docs_url=config("docs_url", default=""), redoc_url=config("redoc_url", default="")) print("============= ALERTS =============") diff --git a/ee/api/app.py b/ee/api/app.py index 505f1393c..1e12e6015 100644 --- a/ee/api/app.py +++ b/ee/api/app.py @@ -16,7 +16,7 @@ from routers.crons import core_crons from routers.crons import core_dynamic_crons from routers.subs import dashboard, insights, metrics, v1_api_ee -app = FastAPI(root_path="/api") +app = FastAPI(root_path="/api", docs_url=config("docs_url", default=""), redoc_url=config("redoc_url", default="")) @app.middleware('http') From ef679a275f092ebbbea3633f2b366036cb203674 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Fri, 22 Jul 2022 18:52:30 +0200 Subject: [PATCH 40/47] change(ui) - live sessions maintain query params --- .../shared/SessionItem/PlayLink/PlayLink.tsx | 36 +- .../shared/SessionItem/SessionItem.tsx | 321 +++++++++--------- frontend/app/routes.js | 2 +- 3 files changed, 178 insertions(+), 181 deletions(-) diff --git a/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx b/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx index 54c7ed692..a063641ec 100644 --- a/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx +++ b/frontend/app/components/shared/SessionItem/PlayLink/PlayLink.tsx @@ -1,44 +1,42 @@ -import React, { useState, useEffect } from 'react' -import { - Link, - Icon, - } from 'UI'; +import React, { useState, useEffect } from 'react'; +import { Link, Icon } from 'UI'; import { session as sessionRoute, liveSession as liveSessionRoute } from 'App/routes'; const PLAY_ICON_NAMES = { notPlayed: 'play-fill', played: 'play-circle-light', - hovered: 'play-hover' -} + hovered: 'play-hover', +}; -const getDefaultIconName = (isViewed) => !isViewed ? PLAY_ICON_NAMES.notPlayed : PLAY_ICON_NAMES.played +const getDefaultIconName = (isViewed: any) => (!isViewed ? PLAY_ICON_NAMES.notPlayed : PLAY_ICON_NAMES.played); interface Props { isAssist: boolean; viewed: boolean; sessionId: string; onClick?: () => void; + queryParams: any; } export default function PlayLink(props: Props) { - const { isAssist, viewed, sessionId, onClick = null } = props - const defaultIconName = getDefaultIconName(viewed) + const { isAssist, viewed, sessionId, onClick = null, queryParams } = props; + const defaultIconName = getDefaultIconName(viewed); - const [isHovered, toggleHover] = useState(false) - const [iconName, setIconName] = useState(defaultIconName) + const [isHovered, toggleHover] = useState(false); + const [iconName, setIconName] = useState(defaultIconName); useEffect(() => { - if (isHovered) setIconName(PLAY_ICON_NAMES.hovered) - else setIconName(getDefaultIconName(viewed)) - }, [isHovered, viewed]) + if (isHovered) setIconName(PLAY_ICON_NAMES.hovered); + else setIconName(getDefaultIconName(viewed)); + }, [isHovered, viewed]); return ( {}} - to={ isAssist ? liveSessionRoute(sessionId) : sessionRoute(sessionId) } + to={isAssist ? liveSessionRoute(sessionId, queryParams) : sessionRoute(sessionId)} onMouseEnter={() => toggleHover(true)} onMouseLeave={() => toggleHover(false)} > - + - ) -} \ No newline at end of file + ); +} diff --git a/frontend/app/components/shared/SessionItem/SessionItem.tsx b/frontend/app/components/shared/SessionItem/SessionItem.tsx index 17b8122c3..fa886ab8b 100644 --- a/frontend/app/components/shared/SessionItem/SessionItem.tsx +++ b/frontend/app/components/shared/SessionItem/SessionItem.tsx @@ -1,192 +1,191 @@ -import React from 'react' +import React, { useEffect } from 'react'; import cn from 'classnames'; -import { - CountryFlag, - Avatar, - TextEllipsis, - Label, - Icon, -} from 'UI'; +import { CountryFlag, Avatar, TextEllipsis, Label, Icon } from 'UI'; import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; import { durationFormatted, formatTimeOrDate } from 'App/date'; import stl from './sessionItem.module.css'; -import Counter from './Counter' +import Counter from './Counter'; import { withRouter, RouteComponentProps } from 'react-router-dom'; import SessionMetaList from './SessionMetaList'; import PlayLink from './PlayLink'; import ErrorBars from './ErrorBars'; -import { assist as assistRoute, liveSession, sessions as sessionsRoute, isRoute } from "App/routes"; +import { assist as assistRoute, liveSession, sessions as sessionsRoute, isRoute } from 'App/routes'; import { capitalize } from 'App/utils'; const ASSIST_ROUTE = assistRoute(); -const ASSIST_LIVE_SESSION = liveSession() +const ASSIST_LIVE_SESSION = liveSession(); const SESSIONS_ROUTE = sessionsRoute(); interface Props { - session: { - sessionId: string; - userBrowser: string; - userOs: string; - userId: string; - userAnonymousId: string; - userDisplayName: string; - userCountry: string; - startedAt: number; - duration: string; - eventsCount: number; - errorsCount: number; - pagesCount: number; - viewed: boolean; - favorite: boolean; - userDeviceType: string; - userUuid: string; - userNumericHash: number; - live: boolean; - metadata: Record; - userSessionsCount: number; - issueTypes: []; - active: boolean; - }, - onUserClick?: (userId: string, userAnonymousId: string) => void; - hasUserFilter?: boolean; - disableUser?: boolean; - metaList?: Array; - // showActive?: boolean; - lastPlayedSessionId?: string; - live?: boolean; - onClick?: any + session: { + sessionId: string; + userBrowser: string; + userOs: string; + userId: string; + userAnonymousId: string; + userDisplayName: string; + userCountry: string; + startedAt: number; + duration: string; + eventsCount: number; + errorsCount: number; + pagesCount: number; + viewed: boolean; + favorite: boolean; + userDeviceType: string; + userUuid: string; + userNumericHash: number; + live: boolean; + metadata: Record; + userSessionsCount: number; + issueTypes: []; + active: boolean; + }; + onUserClick?: (userId: string, userAnonymousId: string) => void; + hasUserFilter?: boolean; + disableUser?: boolean; + metaList?: Array; + // showActive?: boolean; + lastPlayedSessionId?: string; + live?: boolean; + onClick?: any; } function SessionItem(props: RouteComponentProps & Props) { - const { settingsStore } = useStore(); - const { timezone } = settingsStore.sessionSettings; + const { settingsStore } = useStore(); + const { timezone } = settingsStore.sessionSettings; + const [isIframe, setIsIframe] = React.useState(false); - const { - session, - onUserClick = () => null, - hasUserFilter = false, - disableUser = false, - metaList = [], - lastPlayedSessionId, - onClick = null, - } = props; + const { + session, + onUserClick = () => null, + hasUserFilter = false, + disableUser = false, + metaList = [], + lastPlayedSessionId, + onClick = null, + } = props; - const { - sessionId, - userBrowser, - userOs, - userId, - userAnonymousId, - userDisplayName, - userCountry, - startedAt, - duration, - eventsCount, - viewed, - userDeviceType, - userNumericHash, - live, - metadata, - issueTypes, - active, - } = session; + const { + sessionId, + userBrowser, + userOs, + userId, + userAnonymousId, + userDisplayName, + userCountry, + startedAt, + duration, + eventsCount, + viewed, + userDeviceType, + userNumericHash, + live, + metadata, + issueTypes, + active, + } = session; - const location = props.location; + const location = props.location; + const queryParams = Object.fromEntries(new URLSearchParams(location.search)); - const formattedDuration = durationFormatted(duration); - const hasUserId = userId || userAnonymousId; - const isSessions = isRoute(SESSIONS_ROUTE, location.pathname); - const isAssist = isRoute(ASSIST_ROUTE, location.pathname) || isRoute(ASSIST_LIVE_SESSION, location.pathname); - const isLastPlayed = lastPlayedSessionId === sessionId; + const formattedDuration = durationFormatted(duration); + const hasUserId = userId || userAnonymousId; + const isSessions = isRoute(SESSIONS_ROUTE, location.pathname); + const isAssist = isRoute(ASSIST_ROUTE, location.pathname) || isRoute(ASSIST_LIVE_SESSION, location.pathname); + const isLastPlayed = lastPlayedSessionId === sessionId; - const _metaList = Object.keys(metadata).filter(i => metaList.includes(i)).map(key => { - const value = metadata[key]; - return { label: key, value }; - }); + const _metaList = Object.keys(metadata) + .filter((i) => metaList.includes(i)) + .map((key) => { + const value = metadata[key]; + return { label: key, value }; + }); - return ( -
e.stopPropagation()}> -
-
-
-
-
-
(!disableUser && !hasUserFilter) && onUserClick(userId, userAnonymousId)} - > - + return ( +
e.stopPropagation()}> +
+
+
+
+ +
+
+
!disableUser && !hasUserFilter && onUserClick(userId, userAnonymousId)} + > + +
+
+
+
+
+ +
+
+ {!isAssist && ( + <> +
+ {eventsCount} + {eventsCount === 0 || eventsCount > 1 ? 'Events' : 'Event'} +
+ + + )} +
{live ? : formattedDuration}
+
+
+
+
+ +
+
+ + + + + + + + + + + +
+
+ {isSessions && ( +
+ +
+ )}
-
-
-
-
- -
-
- {!isAssist && ( - <> -
- { eventsCount } - { eventsCount === 0 || eventsCount > 1 ? 'Events' : 'Event' } -
- - - )} -
{ live ? : formattedDuration }
-
-
-
-
- -
-
- - - - - - - - - - - -
-
- { isSessions && ( -
- -
- )} -
-
-
- { isSessions && ( -
- { isLastPlayed && ( - - )} +
+
+ {isSessions && ( +
+ {isLastPlayed && ( + + )} +
+ )} + +
- )} -
-
+ {_metaList.length > 0 && }
- { _metaList.length > 0 && ( - - )} -
- ) + ); } -export default withRouter(observer(SessionItem)) +export default withRouter(observer(SessionItem)); diff --git a/frontend/app/routes.js b/frontend/app/routes.js index b1e241292..627095f86 100644 --- a/frontend/app/routes.js +++ b/frontend/app/routes.js @@ -86,7 +86,7 @@ export const sessions = params => queried('/sessions', params); export const assist = params => queried('/assist', params); export const session = (sessionId = ':sessionId', hash) => hashed(`/session/${ sessionId }`, hash); -export const liveSession = (sessionId = ':sessionId', hash) => hashed(`/assist/${ sessionId }`, hash); +export const liveSession = (sessionId = ':sessionId', params, hash) => hashed(queried(`/assist/${ sessionId }`, params), hash); // export const liveSession = (sessionId = ':sessionId', hash) => hashed(`/live/session/${ sessionId }`, hash); export const errors = params => queried('/errors', params); From bdfa17c95b87e17334e5475e8889f17486357cc9 Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Mon, 25 Jul 2022 15:12:59 +0200 Subject: [PATCH 41/47] feat(assist): support search operators feat(chalice): support search operators for assist --- api/chalicelib/core/assist.py | 5 +- api/schemas.py | 2 + ee/utilities/package-lock.json | 12 ++-- ee/utilities/utils/helper-ee.js | 1 + utilities/package-lock.json | 112 ++++++++++++++++---------------- utilities/utils/helper.js | 33 ++++++++-- 6 files changed, 93 insertions(+), 72 deletions(-) diff --git a/api/chalicelib/core/assist.py b/api/chalicelib/core/assist.py index efbc7b5c6..6fc8bcd90 100644 --- a/api/chalicelib/core/assist.py +++ b/api/chalicelib/core/assist.py @@ -35,9 +35,10 @@ def get_live_sessions_ws(project_id, body: schemas.LiveSessionsSearchPayloadSche } for f in body.filters: if f.type == schemas.LiveFilterType.metadata: - data["filter"][f.source] = f.value + data["filter"][f.source] = {"values": f.value, "operator": f.operator} + else: - data["filter"][f.type.value] = f.value + data["filter"][f.type.value] = {"values": f.value, "operator": f.operator} return __get_live_sessions_ws(project_id=project_id, data=data) diff --git a/api/schemas.py b/api/schemas.py index f0f20e657..314a0f7d2 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -1031,6 +1031,8 @@ class LiveSessionSearchFilterSchema(BaseModel): value: Union[List[str], str] = Field(...) type: LiveFilterType = Field(...) source: Optional[str] = Field(None) + operator: Literal[SearchEventOperator._is.value, + SearchEventOperator._contains.value] = Field(SearchEventOperator._contains.value) @root_validator def validator(cls, values): diff --git a/ee/utilities/package-lock.json b/ee/utilities/package-lock.json index 8aa6c9196..6b9dbdf1c 100644 --- a/ee/utilities/package-lock.json +++ b/ee/utilities/package-lock.json @@ -112,9 +112,9 @@ "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" }, "node_modules/@types/node": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz", - "integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==" + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.1.tgz", + "integrity": "sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg==" }, "node_modules/accepts": { "version": "1.3.8", @@ -1179,9 +1179,9 @@ "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" }, "@types/node": { - "version": "18.0.3", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.0.3.tgz", - "integrity": "sha512-HzNRZtp4eepNitP+BD6k2L6DROIDG4Q0fm4x+dwfsr6LGmROENnok75VGw40628xf+iR24WeMFcHuuBDUAzzsQ==" + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.1.tgz", + "integrity": "sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg==" }, "accepts": { "version": "1.3.8", diff --git a/ee/utilities/utils/helper-ee.js b/ee/utilities/utils/helper-ee.js index 50b414b7a..86997f0c4 100644 --- a/ee/utilities/utils/helper-ee.js +++ b/ee/utilities/utils/helper-ee.js @@ -91,6 +91,7 @@ const extractPayloadFromRequest = async function (req, res) { return helper.extractPayloadFromRequest(req); } filters.filter = helper.objectToObjectOfArrays(filters.filter); + filters.filter = helper.transformFilters(filters.filter); debug && console.log("payload/filters:" + JSON.stringify(filters)) return Object.keys(filters).length > 0 ? filters : undefined; } diff --git a/utilities/package-lock.json b/utilities/package-lock.json index 8e90703f3..f4eb45944 100644 --- a/utilities/package-lock.json +++ b/utilities/package-lock.json @@ -42,9 +42,9 @@ "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" }, "node_modules/@types/node": { - "version": "17.0.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.42.tgz", - "integrity": "sha512-Q5BPGyGKcvQgAMbsr7qEGN/kIPN6zZecYYABeTDBizOsau+2NMdSVTar9UQw21A2+JyA2KRNDYaYrPB0Rpk2oQ==" + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.1.tgz", + "integrity": "sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg==" }, "node_modules/accepts": { "version": "1.3.8", @@ -61,12 +61,12 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", "engines": { "node": ">=0.8" } @@ -175,9 +175,9 @@ } }, "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", "engines": { "node": ">= 0.6" } @@ -185,12 +185,12 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -270,6 +270,14 @@ "node": ">=10.0.0" } }, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/engine.io/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -345,18 +353,10 @@ "node": ">= 0.10.0" } }, - "node_modules/express/node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "engines": [ "node >=0.6.0" ] @@ -504,7 +504,7 @@ "node_modules/lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" + "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" }, "node_modules/map-obj": { "version": "4.3.0", @@ -541,12 +541,12 @@ "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", "engines": { "node": ">= 0.6" } @@ -641,7 +641,7 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -808,9 +808,9 @@ "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==" }, "node_modules/socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz", + "integrity": "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==", "dependencies": { "@types/component-emitter": "^1.2.10", "component-emitter": "~1.3.0", @@ -938,7 +938,7 @@ "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", "engines": { "node": ">= 0.4.0" } @@ -946,7 +946,7 @@ "node_modules/vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", "engines": { "node": ">= 0.8" } @@ -954,7 +954,7 @@ "node_modules/verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "engines": [ "node >=0.6.0" ], @@ -1013,9 +1013,9 @@ "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" }, "@types/node": { - "version": "17.0.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.42.tgz", - "integrity": "sha512-Q5BPGyGKcvQgAMbsr7qEGN/kIPN6zZecYYABeTDBizOsau+2NMdSVTar9UQw21A2+JyA2KRNDYaYrPB0Rpk2oQ==" + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.6.1.tgz", + "integrity": "sha512-z+2vB6yDt1fNwKOeGbckpmirO+VBDuQqecXkgeIqDlaOtmKn6hPR/viQ8cxCfqLU4fTlvM3+YjM367TukWdxpg==" }, "accepts": { "version": "1.3.8", @@ -1029,12 +1029,12 @@ "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==" }, "base64id": { "version": "2.0.0", @@ -1109,19 +1109,19 @@ "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" }, "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, "cors": { "version": "2.8.5", @@ -1177,6 +1177,11 @@ "ws": "~8.2.3" }, "dependencies": { + "cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -1243,19 +1248,12 @@ "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" - }, - "dependencies": { - "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" - } } }, "extsprintf": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==" }, "finalhandler": { "version": "1.2.0", @@ -1367,7 +1365,7 @@ "lodash.set": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", - "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM=" + "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" }, "map-obj": { "version": "4.3.0", @@ -1391,12 +1389,12 @@ "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" }, "methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", - "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" }, "mime": { "version": "1.6.0", @@ -1457,7 +1455,7 @@ "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" }, "proxy-addr": { "version": "2.0.7", @@ -1594,9 +1592,9 @@ "integrity": "sha512-W4N+o69rkMEGVuk2D/cvca3uYsvGlMwsySWV447y99gUPghxq42BxqLNMndb+a1mm/5/7NeXVQS7RLa2XyXvYg==" }, "socket.io-parser": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", - "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.5.tgz", + "integrity": "sha512-sNjbT9dX63nqUFIOv95tTVm6elyIU4RvB1m8dOeZt+IgWwcWklFDOdmGcfo3zSiRsnR/3pJkjY5lfoGqEe4Eig==", "requires": { "@types/component-emitter": "^1.2.10", "component-emitter": "~1.3.0", @@ -1660,17 +1658,17 @@ "utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", - "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" }, "vary": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, "verror": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", "requires": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", diff --git a/utilities/utils/helper.js b/utilities/utils/helper.js index 7088d2b77..f31b9e0ba 100644 --- a/utilities/utils/helper.js +++ b/utilities/utils/helper.js @@ -40,19 +40,20 @@ const extractSessionIdFromRequest = function (req) { } const isValidSession = function (sessionInfo, filters) { let foundAll = true; - for (const [key, values] of Object.entries(filters)) { + for (const [key, body] of Object.entries(filters)) { let found = false; - if (values !== undefined && values !== null) { + if (body.values !== undefined && body.values !== null) { for (const [skey, svalue] of Object.entries(sessionInfo)) { if (svalue !== undefined && svalue !== null) { if (typeof (svalue) === "object") { - if (isValidSession(svalue, {[key]: values})) { + if (isValidSession(svalue, {[key]: body})) { found = true; break; } } else if (skey.toLowerCase() === key.toLowerCase()) { - for (let v of values) { - if (String(svalue).toLowerCase().indexOf(v.toLowerCase()) >= 0) { + for (let v of body["values"]) { + if (body.operator === "is" && String(svalue).toLowerCase() === v.toLowerCase() + || body.operator !== "is" && String(svalue).toLowerCase().indexOf(v.toLowerCase()) >= 0) { found = true; break; } @@ -108,10 +109,26 @@ const objectToObjectOfArrays = function (obj) { } return _obj; } +const transformFilters = function (filter) { + for (let key of Object.keys(filter)) { + //To support old v1.7.0 payload + if (Array.isArray(filter[key]) || filter[key] === undefined || filter[key] === null) { + debug && console.log(`[WS]old format for key=${key}`); + filter[key] = {"values": filter[key]}; + } + if (filter[key].operator) { + debug && console.log(`[WS]where operator=${filter[key].operator}`); + } else { + debug && console.log(`[WS]where operator=DEFAULT-contains`); + filter[key].operator = "contains"; + } + } + return filter; +} const extractPayloadFromRequest = function (req) { let filters = { - "query": {}, - "filter": {}, + "query": {}, // for autocomplete + "filter": {}, // for sessions search "sort": { "key": req.body.sort && req.body.sort.key ? req.body.sort.key : undefined, "order": req.body.sort && req.body.sort.order === "DESC" @@ -135,6 +152,7 @@ const extractPayloadFromRequest = function (req) { } filters.filter = objectToObjectOfArrays(filters.filter); filters.filter = {...filters.filter, ...(req.body.filter || {})}; + filters.filter = transformFilters(filters.filter); debug && console.log("payload/filters:" + JSON.stringify(filters)) return filters; } @@ -194,6 +212,7 @@ const uniqueAutocomplete = function (list) { return _list; } module.exports = { + transformFilters, extractPeerId, request_logger, getValidAttributes, From 04eaf84e4cf1e05213d84c8e3ed2bf11a1d58418 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 25 Jul 2022 16:47:28 +0200 Subject: [PATCH 42/47] fix(ui) - active sessions modal scroll --- .../components/Assist/components/SessionList/SessionList.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/Assist/components/SessionList/SessionList.tsx b/frontend/app/components/Assist/components/SessionList/SessionList.tsx index ed0af5625..dc8b54025 100644 --- a/frontend/app/components/Assist/components/SessionList/SessionList.tsx +++ b/frontend/app/components/Assist/components/SessionList/SessionList.tsx @@ -24,7 +24,7 @@ function SessionList(props: Props) { return (
-
+
{props.userId}'s Live Sessions{' '} From 2a43c048641a304bef31b0b2eadb8bf38087e5aa Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Mon, 25 Jul 2022 17:01:56 +0200 Subject: [PATCH 43/47] fix(ui) - integration project dropdown --- .../app/components/Client/Integrations/IntegrationForm.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/app/components/Client/Integrations/IntegrationForm.js b/frontend/app/components/Client/Integrations/IntegrationForm.js index a26576fc3..aeb28fe31 100644 --- a/frontend/app/components/Client/Integrations/IntegrationForm.js +++ b/frontend/app/components/Client/Integrations/IntegrationForm.js @@ -35,9 +35,9 @@ export default class IntegrationForm extends React.PureComponent { onChangeSelect = ({ value }) => { const { sites, list, name } = this.props; - const site = sites.find(s => s.id === value); + const site = sites.find(s => s.id === value.value); this.setState({ currentSiteId: site.id }) - this.init(value); + this.init(value.value); } init = (siteId) => { From b65f45bf031a09a2be46b6e9cee5cbf066de0f6e Mon Sep 17 00:00:00 2001 From: sylenien Date: Mon, 25 Jul 2022 17:26:09 +0200 Subject: [PATCH 44/47] feat(tracker): cut orphan child nodes to prevent memory leaks --- tracker/tracker-assist/package.json | 2 +- tracker/tracker-axios/src/index.ts | 2 +- tracker/tracker/package.json | 2 +- tracker/tracker/src/main/app/index.ts | 9 ++++-- tracker/tracker/src/main/app/nodes.ts | 32 +++++++++++++------ .../tracker/src/main/app/observer/observer.ts | 26 ++++++++++++--- tracker/tracker/src/main/modules/input.ts | 2 ++ tracker/tracker/src/webworker/QueueSender.ts | 3 -- 8 files changed, 55 insertions(+), 23 deletions(-) diff --git a/tracker/tracker-assist/package.json b/tracker/tracker-assist/package.json index 3d363cffd..d04faef0d 100644 --- a/tracker/tracker-assist/package.json +++ b/tracker/tracker-assist/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker-assist", "description": "Tracker plugin for screen assistance through the WebRTC", - "version": "3.5.15", + "version": "3.5.16", "keywords": [ "WebRTC", "assistance", diff --git a/tracker/tracker-axios/src/index.ts b/tracker/tracker-axios/src/index.ts index e7abce84e..14d3387dc 100644 --- a/tracker/tracker-axios/src/index.ts +++ b/tracker/tracker-axios/src/index.ts @@ -216,4 +216,4 @@ export default function(opts: Partial = {}) { return Promise.reject(error); }); } -} \ No newline at end of file +} diff --git a/tracker/tracker/package.json b/tracker/tracker/package.json index 183006c05..7a6fdbe01 100644 --- a/tracker/tracker/package.json +++ b/tracker/tracker/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker", "description": "The OpenReplay tracker main package", - "version": "3.5.15", + "version": "3.5.16", "keywords": [ "logging", "replay" diff --git a/tracker/tracker/src/main/app/index.ts b/tracker/tracker/src/main/app/index.ts index be03a968c..16d472c90 100644 --- a/tracker/tracker/src/main/app/index.ts +++ b/tracker/tracker/src/main/app/index.ts @@ -426,6 +426,7 @@ export default class App { this.ticker.start(); this.notify.log("OpenReplay tracking started."); + // get rid of onStart ? if (typeof this.options.onStart === 'function') { this.options.onStart(onStartInfo) @@ -458,7 +459,7 @@ export default class App { }) } } - stop(calledFromAPI = false): void { + stop(calledFromAPI = false, restarting = false): void { if (this.activityState !== ActivityState.NotActive) { try { this.sanitizer.clear() @@ -470,7 +471,7 @@ export default class App { this.session.reset() } this.notify.log("OpenReplay tracking stopped.") - if (this.worker) { + if (this.worker && !restarting) { this.worker.postMessage("stop") } } finally { @@ -478,4 +479,8 @@ export default class App { } } } + restart() { + this.stop(false, true); + this.start({ forceNew: false }); + } } diff --git a/tracker/tracker/src/main/app/nodes.ts b/tracker/tracker/src/main/app/nodes.ts index a1c87b6e2..536ba4efc 100644 --- a/tracker/tracker/src/main/app/nodes.ts +++ b/tracker/tracker/src/main/app/nodes.ts @@ -2,14 +2,14 @@ type NodeCallback = (node: Node, isStart: boolean) => void; type ElementListener = [string, EventListener]; export default class Nodes { - private readonly nodes: Array; - private readonly nodeCallbacks: Array; - private readonly elementListeners: Map>; - constructor(private readonly node_id: string) { - this.nodes = []; - this.nodeCallbacks = []; - this.elementListeners = new Map(); - } + private nodes: Array = []; + private readonly nodeCallbacks: Array = []; + private readonly elementListeners: Map> = new Map(); + + constructor( + private readonly node_id: string, + ) {} + attachNodeCallback(nodeCallback: NodeCallback): void { this.nodeCallbacks.push(nodeCallback); } @@ -46,7 +46,7 @@ export default class Nodes { const id = (node as any)[this.node_id]; if (id !== undefined) { delete (node as any)[this.node_id]; - this.nodes[id] = undefined; + delete this.nodes[id]; const listeners = this.elementListeners.get(id); if (listeners !== undefined) { this.elementListeners.delete(id); @@ -57,13 +57,25 @@ export default class Nodes { } return id; } + cleanTree() { + // sadly we keep empty items in array here resulting in some memory still being used + // but its still better than keeping dead nodes or undef elements + // plus we keep our index positions for new/alive nodes + // performance test: 3ms for 30k nodes with 17k dead ones + for (let i = 0; i < this.nodes.length; i++) { + const node = this.nodes[i]; + if (node && !document.contains(node)) { + this.unregisterNode(node); + } + } + } callNodeCallbacks(node: Node, isStart: boolean): void { this.nodeCallbacks.forEach((cb) => cb(node, isStart)); } getID(node: Node): number | undefined { return (node as any)[this.node_id]; } - getNode(id: number): Node | undefined { + getNode(id: number) { return this.nodes[id]; } diff --git a/tracker/tracker/src/main/app/observer/observer.ts b/tracker/tracker/src/main/app/observer/observer.ts index 940a7eefb..8c59d6029 100644 --- a/tracker/tracker/src/main/app/observer/observer.ts +++ b/tracker/tracker/src/main/app/observer/observer.ts @@ -48,10 +48,17 @@ function isObservable(node: Node): boolean { - use document as a 0-node in the upper context (should be updated in player at first) */ +/* + Nikita: + - rn we only send unbind event for parent (all child nodes will be cut in the live replay anyways) + to prevent sending 1k+ unbinds for child nodes and making replay file bigger than it should be +*/ + enum RecentsType { New, Removed, Changed, + RemovedChild, } export default abstract class Observer { @@ -73,7 +80,7 @@ export default abstract class Observer { } if (type === 'childList') { for (let i = 0; i < mutation.removedNodes.length; i++) { - this.bindTree(mutation.removedNodes[i]); + this.bindTree(mutation.removedNodes[i], true); } for (let i = 0; i < mutation.addedNodes.length; i++) { this.bindTree(mutation.addedNodes[i]); @@ -188,8 +195,12 @@ export default abstract class Observer { this.recents.set(id, RecentsType.Removed) } } + private unbindChildNode(node: Node): void { + const [ id ]= this.app.nodes.registerNode(node); + this.recents.set(id, RecentsType.RemovedChild) + } - private bindTree(node: Node): void { + private bindTree(node: Node, isChildUnbinding: boolean = false): void { if (!isObservable(node)) { return } @@ -199,7 +210,8 @@ export default abstract class Observer { NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, { acceptNode: (node) => - isIgnored(node) || this.app.nodes.getID(node) !== undefined + isIgnored(node) + || (this.app.nodes.getID(node) !== undefined && !isChildUnbinding) ? NodeFilter.FILTER_REJECT : NodeFilter.FILTER_ACCEPT, }, @@ -207,11 +219,15 @@ export default abstract class Observer { false, ); while (walker.nextNode()) { - this.bindNode(walker.currentNode); + if (isChildUnbinding) { + this.unbindChildNode(walker.currentNode); + } else { + this.bindNode(walker.currentNode); + } } } - private unbindNode(node: Node): void { + private unbindNode(node: Node) { const id = this.app.nodes.unregisterNode(node); if (id !== undefined && this.recents.get(id) === RecentsType.Removed) { this.app.send(new RemoveNode(id)); diff --git a/tracker/tracker/src/main/modules/input.ts b/tracker/tracker/src/main/modules/input.ts index 496d642a2..f4d80ebf0 100644 --- a/tracker/tracker/src/main/modules/input.ts +++ b/tracker/tracker/src/main/modules/input.ts @@ -149,6 +149,7 @@ export default function (app: App, opts: Partial): void { app.ticker.attach((): void => { inputValues.forEach((value, id) => { const node = app.nodes.getNode(id); + if (!node) return; if (!isTextEditable(node)) { inputValues.delete(id); return; @@ -164,6 +165,7 @@ export default function (app: App, opts: Partial): void { }); checkableValues.forEach((checked, id) => { const node = app.nodes.getNode(id); + if (!node) return; if (!isCheckable(node)) { checkableValues.delete(id); return; diff --git a/tracker/tracker/src/webworker/QueueSender.ts b/tracker/tracker/src/webworker/QueueSender.ts index d4686539d..b5fc8c8ee 100644 --- a/tracker/tracker/src/webworker/QueueSender.ts +++ b/tracker/tracker/src/webworker/QueueSender.ts @@ -102,6 +102,3 @@ export default class QueueSender { } } - - - From 4e8ce5ce6c434575e6d205e83f53172d813c02dd Mon Sep 17 00:00:00 2001 From: Taha Yassine Kraiem Date: Mon, 25 Jul 2022 17:43:44 +0200 Subject: [PATCH 45/47] feat(assist): fixed objectToObjectOfArrays --- utilities/utils/helper.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utilities/utils/helper.js b/utilities/utils/helper.js index f31b9e0ba..b012ccf6c 100644 --- a/utilities/utils/helper.js +++ b/utilities/utils/helper.js @@ -98,11 +98,11 @@ const objectToObjectOfArrays = function (obj) { for (let k of Object.keys(obj)) { if (obj[k] !== undefined && obj[k] !== null) { _obj[k] = obj[k]; - if (!Array.isArray(_obj[k])) { + if (!Array.isArray(_obj[k].values)) { _obj[k] = [_obj[k]]; } - for (let i = 0; i < _obj[k].length; i++) { - _obj[k][i] = String(_obj[k][i]); + for (let i = 0; i < _obj[k].values.length; i++) { + _obj[k].values[i] = String(_obj[k].values[i]); } } } From 49b961968f5f69fe38002836a98de366abfb49ff Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Tue, 26 Jul 2022 14:48:54 +0200 Subject: [PATCH 46/47] fix(ui) - smtp check --- .../components/Client/Users/components/UserForm/UserForm.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontend/app/components/Client/Users/components/UserForm/UserForm.tsx b/frontend/app/components/Client/Users/components/UserForm/UserForm.tsx index d2df0431d..477e42d8f 100644 --- a/frontend/app/components/Client/Users/components/UserForm/UserForm.tsx +++ b/frontend/app/components/Client/Users/components/UserForm/UserForm.tsx @@ -153,6 +153,7 @@ function UserForm(props: Props) { )); } -export default connect(state => ({ +export default connect((state: any) => ({ isEnterprise: state.getIn([ 'user', 'account', 'edition' ]) === 'ee', + isSmtp: state.getIn([ 'user', 'account', 'smtp' ]), }))(UserForm); \ No newline at end of file From c36c380a5d87ac6ff88ddbdccbff06ab59834264 Mon Sep 17 00:00:00 2001 From: Delirium Date: Tue, 26 Jul 2022 17:06:15 +0300 Subject: [PATCH 47/47] fix(ui): fix timezone settings (#643) --- .../SessionList/SessionListHeader.js | 12 +++--- .../SelectDateRange/SelectDateRange.tsx | 4 +- frontend/app/dateRange.js | 38 ++++++++-------- frontend/app/store.js | 7 ++- frontend/app/types/app/period.js | 43 ++++++++----------- 5 files changed, 53 insertions(+), 51 deletions(-) diff --git a/frontend/app/components/BugFinder/SessionList/SessionListHeader.js b/frontend/app/components/BugFinder/SessionList/SessionListHeader.js index 5e2702639..606ecaf67 100644 --- a/frontend/app/components/BugFinder/SessionList/SessionListHeader.js +++ b/frontend/app/components/BugFinder/SessionList/SessionListHeader.js @@ -26,7 +26,7 @@ function SessionListHeader({ activeTab, count, applyFilter, filter }) { }, [label]); const { startDate, endDate, rangeValue } = filter; - const period = new Record({ start: startDate, end: endDate, rangeName: rangeValue }); + const period = new Record({ start: startDate, end: endDate, rangeName: rangeValue, timezoneOffset: getTimeZoneOffset() }); const onDateChange = (e) => { const dateValues = e.toJSON(); @@ -36,10 +36,12 @@ function SessionListHeader({ activeTab, count, applyFilter, filter }) { }; React.useEffect(() => { - const dateValues = period.toJSON(); - dateValues.startDate = moment(dateValues.startDate).startOf('day').utcOffset(getTimeZoneOffset(), true).valueOf(); - dateValues.endDate = moment(dateValues.endDate).endOf('day').utcOffset(getTimeZoneOffset(), true).valueOf(); - applyFilter(dateValues); + if (label) { + const dateValues = period.toJSON(); + dateValues.startDate = moment(dateValues.startDate).startOf('day').utcOffset(getTimeZoneOffset(), true).valueOf(); + dateValues.endDate = moment(dateValues.endDate).endOf('day').utcOffset(getTimeZoneOffset(), true).valueOf(); + applyFilter(dateValues); + } }, [label]); return ( diff --git a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx index da8a940a5..7eaabc252 100644 --- a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx +++ b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx @@ -39,7 +39,7 @@ function SelectDateRange(props: Props) { }; const isCustomRange = period.rangeName === CUSTOM_RANGE; - const customRange = isCustomRange ? period.rangeFormatted(undefined, timezone) : ''; + const customRange = isCustomRange ? period.rangeFormatted() : ''; return (