diff --git a/api/chalicelib/core/assist.py b/api/chalicelib/core/assist.py index 1804da669..5ff067229 100644 --- a/api/chalicelib/core/assist.py +++ b/api/chalicelib/core/assist.py @@ -34,7 +34,10 @@ def get_live_sessions_ws(project_id, body: schemas.LiveSessionsSearchPayloadSche "sort": {"key": body.sort, "order": body.order} } for f in body.filters: - data["filter"][f.type] = f.value + if f.type == schemas.LiveFilterType.metadata: + data["filter"][f.source] = f.value + else: + data["filter"][f.type.value] = f.value return __get_live_sessions_ws(project_id=project_id, data=data) diff --git a/api/schemas.py b/api/schemas.py index 77a5db26d..45a7bc3d8 100644 --- a/api/schemas.py +++ b/api/schemas.py @@ -1018,25 +1018,32 @@ class LiveFilterType(str, Enum): user_id = FilterType.user_id.value user_anonymous_id = FilterType.user_anonymous_id.value rev_id = FilterType.rev_id.value - page_title = "pageTitle" - # - # platform = "PLATFORM" - # metadata = "METADATA" - # issue = "ISSUE" - # events_count = "EVENTS_COUNT" - # utm_source = "UTM_SOURCE" - # utm_medium = "UTM_MEDIUM" - # utm_campaign = "UTM_CAMPAIGN" + page_title = "PAGETITLE" + session_id = "SESSIONID" + metadata = "METADATA" + user_UUID = "USERUUID" + tracker_version = "TRACKERVERSION" + user_browser_version = "USERBROWSERVERSION" + user_device_type = "USERDEVICETYPE", + timestamp = "TIMESTAMP" class LiveSessionSearchFilterSchema(BaseModel): value: Union[List[str], str] = Field(...) type: LiveFilterType = Field(...) + source: Optional[str] = Field(None) + + @root_validator + def validator(cls, values): + if values.get("type") is not None and values["type"] == LiveFilterType.metadata.value: + assert values.get("source") is not None, "source should not be null for METADATA type" + assert len(values.get("source")) > 0, "source should not be empty for METADATA type" + return values class LiveSessionsSearchPayloadSchema(_PaginatedSchema): filters: List[LiveSessionSearchFilterSchema] = Field([]) - sort: str = Field(default="timestamp") + sort: LiveFilterType = Field(default=LiveFilterType.timestamp) order: SortOrderType = Field(default=SortOrderType.desc) @root_validator(pre=True) diff --git a/ee/utilities/servers/websocket-cluster.js b/ee/utilities/servers/websocket-cluster.js index 6dd69a4bc..f414939fe 100644 --- a/ee/utilities/servers/websocket-cluster.js +++ b/ee/utilities/servers/websocket-cluster.js @@ -93,7 +93,7 @@ const socketsList = async function (req, res) { const connected_sockets = await io.in(peerId).fetchSockets(); for (let item of connected_sockets) { if (item.handshake.query.identity === IDENTITIES.session && item.handshake.query.sessionInfo - && isValidSession(item.handshake.query.sessionInfo, filters)) { + && isValidSession(item.handshake.query.sessionInfo, filters.filter)) { liveSessions[projectKey].push(sessionId); } } @@ -122,7 +122,7 @@ const socketsListByProject = async function (req, res) { const connected_sockets = await io.in(peerId).fetchSockets(); for (let item of connected_sockets) { if (item.handshake.query.identity === IDENTITIES.session && item.handshake.query.sessionInfo - && isValidSession(item.handshake.query.sessionInfo, filters)) { + && isValidSession(item.handshake.query.sessionInfo, filters.filter)) { liveSessions[projectKey].push(sessionId); } } @@ -150,7 +150,7 @@ const socketsLive = async function (req, res) { if (item.handshake.query.identity === IDENTITIES.session) { liveSessions[projectKey] = liveSessions[projectKey] || []; if (hasFilters(filters)) { - if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters)) { + if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters.filter)) { liveSessions[projectKey].push(item.handshake.query.sessionInfo); } } else { @@ -181,7 +181,7 @@ const socketsLiveByProject = async function (req, res) { if (item.handshake.query.identity === IDENTITIES.session) { liveSessions[projectKey] = liveSessions[projectKey] || []; if (hasFilters(filters)) { - if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters)) { + if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters.filter)) { liveSessions[projectKey].push(item.handshake.query.sessionInfo); } } else { diff --git a/ee/utilities/servers/websocket.js b/ee/utilities/servers/websocket.js index dac389fa8..686b62293 100644 --- a/ee/utilities/servers/websocket.js +++ b/ee/utilities/servers/websocket.js @@ -75,7 +75,7 @@ const socketsList = async function (req, res) { const connected_sockets = await io.in(peerId).fetchSockets(); for (let item of connected_sockets) { if (item.handshake.query.identity === IDENTITIES.session && item.handshake.query.sessionInfo - && isValidSession(item.handshake.query.sessionInfo, filters)) { + && isValidSession(item.handshake.query.sessionInfo, filters.filter)) { liveSessions[projectKey].push(sessionId); } } @@ -104,7 +104,7 @@ const socketsListByProject = async function (req, res) { const connected_sockets = await io.in(peerId).fetchSockets(); for (let item of connected_sockets) { if (item.handshake.query.identity === IDENTITIES.session && item.handshake.query.sessionInfo - && isValidSession(item.handshake.query.sessionInfo, filters)) { + && isValidSession(item.handshake.query.sessionInfo, filters.filter)) { liveSessions[projectKey].push(sessionId); } } @@ -132,7 +132,7 @@ const socketsLive = async function (req, res) { if (item.handshake.query.identity === IDENTITIES.session) { liveSessions[projectKey] = liveSessions[projectKey] || []; if (hasFilters(filters)) { - if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters)) { + if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters.filter)) { liveSessions[projectKey].push(item.handshake.query.sessionInfo); } } else { @@ -162,7 +162,7 @@ const socketsLiveByProject = async function (req, res) { if (item.handshake.query.identity === IDENTITIES.session) { liveSessions[projectKey] = liveSessions[projectKey] || []; if (hasFilters(filters)) { - if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters)) { + if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters.filter)) { liveSessions[projectKey].push(item.handshake.query.sessionInfo); } } else { diff --git a/ee/utilities/utils/helper-ee.js b/ee/utilities/utils/helper-ee.js index 6ae4039bb..41fe456cb 100644 --- a/ee/utilities/utils/helper-ee.js +++ b/ee/utilities/utils/helper-ee.js @@ -1,4 +1,5 @@ const helper = require('./helper'); +let debug = process.env.debug === "1" || false; const getBodyFromUWSResponse = async function (res) { return new Promise(((resolve, reject) => { let buffer; @@ -51,21 +52,42 @@ const extractSessionIdFromRequest = function (req) { return undefined; } const extractPayloadFromRequest = async function (req, res) { - let filters = {}; + let filters = { + "query": {}, + "filter": {} + }; if (process.env.uws === "true") { + if (req.getQuery("q")) { + debug && console.log(`[WS]where q=${req.getQuery("q")}`); + filters.query.value = [req.getQuery("q")]; + } + if (req.getQuery("key")) { + debug && console.log(`[WS]where key=${req.getQuery("key")}`); + filters.query.key = [req.getQuery("key")]; + } if (req.getQuery("userId")) { debug && console.log(`[WS]where userId=${req.getQuery("userId")}`); filters.userID = [req.getQuery("userId")]; } let body = await getBodyFromUWSResponse(res); - filters = {...filters, ...(body.filter || {})}; + filters = { + ...filters, + "sort": { + "key": body.sort && body.sort.key ? body.sort.key : undefined, + "order": body.sort && body.sort.order === "DESC" + }, + "pagination": { + "limit": body.pagination && body.pagination.limit ? body.pagination.limit : undefined, + "page": body.pagination && body.pagination.page ? body.pagination.page : undefined + } + } + filters.filter = {...filters.filter, ...(body.filter || {})}; } else { - return helper.extractFiltersFromRequest(req); + return helper.extractPayloadFromRequest(req); } - filters = helper.objectToObjectOfArrays({...filters, ...(req.body.filter || {})}); - debug && console.log("payload/filters:") - debug && console.log(JSON.stringify(filters)) + filters.filter = helper.objectToObjectOfArrays(filters.filter); + debug && console.log("payload/filters:" + JSON.stringify(filters)) return Object.keys(filters).length > 0 ? filters : undefined; } module.exports = { diff --git a/utilities/servers/websocket.js b/utilities/servers/websocket.js index 3587d9ad8..59d221042 100644 --- a/utilities/servers/websocket.js +++ b/utilities/servers/websocket.js @@ -89,7 +89,7 @@ const socketsListByProject = async function (req, res) { const connected_sockets = await io.in(peerId).fetchSockets(); for (let item of connected_sockets) { if (item.handshake.query.identity === IDENTITIES.session && item.handshake.query.sessionInfo - && isValidSession(item.handshake.query.sessionInfo, filters)) { + && isValidSession(item.handshake.query.sessionInfo, filters.filter)) { liveSessions[projectKey].push(sessionId); } } @@ -117,7 +117,7 @@ const socketsLive = async function (req, res) { if (item.handshake.query.identity === IDENTITIES.session) { liveSessions[projectKey] = liveSessions[projectKey] || []; if (hasFilters(filters)) { - if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters)) { + if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters.filter)) { liveSessions[projectKey].push(item.handshake.query.sessionInfo); } } else { @@ -146,7 +146,7 @@ const socketsLiveByProject = async function (req, res) { if (item.handshake.query.identity === IDENTITIES.session) { liveSessions[projectKey] = liveSessions[projectKey] || []; if (hasFilters(filters)) { - if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters)) { + if (item.handshake.query.sessionInfo && isValidSession(item.handshake.query.sessionInfo, filters.filter)) { liveSessions[projectKey].push(item.handshake.query.sessionInfo); } } else { diff --git a/utilities/utils/helper.js b/utilities/utils/helper.js index 6e4e1cb5b..de002f89e 100644 --- a/utilities/utils/helper.js +++ b/utilities/utils/helper.js @@ -44,8 +44,8 @@ const isValidSession = function (sessionInfo, filters) { let found = false; for (const [skey, svalue] of Object.entries(sessionInfo)) { if (svalue !== undefined && svalue !== null) { - if (svalue.constructor === Object) { - if (isValidSession(svalue, {key: values})) { + if (typeof (svalue) === "object") { + if (isValidSession(svalue, {[key]: values})) { found = true; break; } @@ -74,7 +74,7 @@ const getValidAttributes = function (sessionInfo, query) { let deduplicate = []; for (const [skey, svalue] of Object.entries(sessionInfo)) { if (svalue !== undefined && svalue !== null) { - if (svalue.constructor === Object) { + if (typeof (svalue) === "object") { matches = [...matches, ...getValidAttributes(svalue, query)] } else if ((query.key === undefined || skey.toLowerCase() === query.key.toLowerCase()) && svalue.toLowerCase().indexOf(query.value.toLowerCase()) >= 0 @@ -110,8 +110,14 @@ const extractPayloadFromRequest = function (req) { let filters = { "query": {}, "filter": {}, - "sort": {"key": undefined, "order": false}, - "pagination": {"limit": undefined, "page": undefined} + "sort": { + "key": req.body.sort && req.body.sort.key ? req.body.sort.key : undefined, + "order": req.body.sort && req.body.sort.order === "DESC" + }, + "pagination": { + "limit": req.body.pagination && req.body.pagination.limit ? req.body.pagination.limit : undefined, + "page": req.body.pagination && req.body.pagination.page ? req.body.pagination.page : undefined + } }; if (req.query.q) { debug && console.log(`[WS]where q=${req.query.q}`); @@ -125,17 +131,23 @@ const extractPayloadFromRequest = function (req) { debug && console.log(`[WS]where userId=${req.query.userId}`); filters.filter.userID = [req.query.userId]; } - filters.filters = objectToObjectOfArrays(filters.filter); - filters = {...filters, ...(req.body.filter || {})}; - debug && console.log("payload/filters:") - debug && console.log(JSON.stringify(filters)) + filters.filter = objectToObjectOfArrays(filters.filter); + filters.filter = {...filters.filter, ...(req.body.filter || {})}; + debug && console.log("payload/filters:" + JSON.stringify(filters)) return filters; } const sortPaginate = function (list, filters) { + let skey = "timestamp"; + if (list.length > 0 && filters.sort.key) { + for (let key of Object.keys(list[0])) { + if (key.toLowerCase() == filters.sort.key.toLowerCase()) { + skey = key; + break; + } + } + } list.sort((a, b) => { - let aV = (a[filters.sort.key] || a["timestamp"]); - let bV = (b[filters.sort.key] || b["timestamp"]); - return aV > bV ? 1 : aV < bV ? -1 : 0; + return a[skey] > b[skey] ? 1 : a[skey] < b[skey] ? -1 : 0; }) if (filters.sort.order) {