From 0dcf06da997c8f341b6f6be9e6687ca074903510 Mon Sep 17 00:00:00 2001 From: Rishabh Date: Fri, 25 Jun 2021 12:05:38 +0530 Subject: [PATCH] Restricted Sentry event capturing to portal events no refs - updates Sentry's `beforeSend` method to restrict and send events originated by portal --- ghost/portal/src/App.js | 29 ++++++++++++++++++++++++++--- ghost/portal/src/utils/helpers.js | 7 +++++++ 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/ghost/portal/src/App.js b/ghost/portal/src/App.js index 5a491282d5..6d72a8b8de 100644 --- a/ghost/portal/src/App.js +++ b/ghost/portal/src/App.js @@ -10,7 +10,7 @@ import * as Fixtures from './utils/fixtures'; import ActionHandler from './actions'; import './App.css'; import NotificationParser from './utils/notifications'; -import {createPopupNotification, getCurrencySymbol, getFirstpromoterId, getQueryPrice, getSiteDomain, isComplimentaryMember, isInviteOnlySite, removePortalLinkFromUrl} from './utils/helpers'; +import {createPopupNotification, getCurrencySymbol, getFirstpromoterId, getQueryPrice, getSiteDomain, isComplimentaryMember, isInviteOnlySite, isSentryEventAllowed, removePortalLinkFromUrl} from './utils/helpers'; const handleDataAttributes = require('./data-attributes'); const React = require('react'); @@ -21,6 +21,23 @@ const DEV_MODE_DATA = { member: Fixtures.member.paid, page: 'signup' }; + +function SentryErrorBoundary({site, children}) { + const {portal_sentry: portalSentry} = site || {}; + if (portalSentry && portalSentry.dsn) { + return ( + + {children} + + ); + } + return ( + <> + {children} + + ); +} + export default class App extends React.Component { constructor(props) { super(props); @@ -385,6 +402,12 @@ export default class App extends React.Component { dsn: portalSentry.dsn, environment: portalSentry.env || 'development', release: releaseTag, + beforeSend: (event) => { + if (isSentryEventAllowed({event})) { + return event; + } + return null; + }, allowUrls: [ /https?:\/\/((www)\.)?unpkg\.com\/@tryghost\/portal/ ] @@ -609,13 +632,13 @@ export default class App extends React.Component { render() { if (this.state.initStatus === 'success') { return ( - + - + ); } return null; diff --git a/ghost/portal/src/utils/helpers.js b/ghost/portal/src/utils/helpers.js index cb525f2940..39f02c33b3 100644 --- a/ghost/portal/src/utils/helpers.js +++ b/ghost/portal/src/utils/helpers.js @@ -27,6 +27,13 @@ export function isCookiesDisabled() { return !(navigator && navigator.cookieEnabled); } +export function isSentryEventAllowed({event: sentryEvent}) { + const frames = sentryEvent?.exception?.values?.[0]?.stacktrace?.frames || []; + const fileNames = frames.map(frame => frame.filename).filter(filename => !!filename); + const lastFileName = fileNames[fileNames.length - 1] || ''; + return lastFileName.includes('@tryghost/portal'); +} + export function getMemberSubscription({member = {}}) { if (isPaidMember({member})) { const subscriptions = member.subscriptions || [];