From cd309b0c774481319999d581fedad97a5a6230b9 Mon Sep 17 00:00:00 2001 From: Abhinav-grd Date: Wed, 1 Sep 2021 13:17:37 +0530 Subject: [PATCH 1/5] update the feild below which error appears --- src/components/SetPasswordForm.tsx | 5 +---- src/components/SignUp.tsx | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/SetPasswordForm.tsx b/src/components/SetPasswordForm.tsx index 0978e3abc..847225dd6 100644 --- a/src/components/SetPasswordForm.tsx +++ b/src/components/SetPasswordForm.tsx @@ -32,10 +32,7 @@ function SetPasswordForm(props: Props) { setFieldError('confirm', constants.PASSPHRASE_MATCH_ERROR); } } catch (e) { - setFieldError( - 'passphrase', - `${constants.UNKNOWN_ERROR} ${e.message}` - ); + setFieldError('confirm', `${constants.UNKNOWN_ERROR} ${e.message}`); } finally { setLoading(false); } diff --git a/src/components/SignUp.tsx b/src/components/SignUp.tsx index 735d5c36e..b6bb39062 100644 --- a/src/components/SignUp.tsx +++ b/src/components/SignUp.tsx @@ -45,7 +45,7 @@ export default function SignUp(props: SignUpProps) { setData(LS_KEYS.USER, { email }); await getOtt(email); } catch (e) { - setFieldError('email', `${constants.UNKNOWN_ERROR} ${e.message}`); + setFieldError('confirm', `${constants.UNKNOWN_ERROR} ${e.message}`); } try { if (passphrase === confirm) { From 39d93c4f79265d8f83deabf4ac5115adfc6fe779 Mon Sep 17 00:00:00 2001 From: Abhinav-grd Date: Wed, 1 Sep 2021 15:33:01 +0530 Subject: [PATCH 2/5] wrap error with context and report to sentry --- src/components/SignUp.tsx | 63 ++++++++++++++++++++--------------- src/utils/common/errorUtil.ts | 22 ++++++++++++ src/utils/sentry/index.ts | 9 ++--- 3 files changed, 62 insertions(+), 32 deletions(-) diff --git a/src/components/SignUp.tsx b/src/components/SignUp.tsx index b6bb39062..4d46dea42 100644 --- a/src/components/SignUp.tsx +++ b/src/components/SignUp.tsx @@ -42,34 +42,45 @@ export default function SignUp(props: SignUpProps) { ) => { setLoading(true); try { - setData(LS_KEYS.USER, { email }); - await getOtt(email); - } catch (e) { - setFieldError('confirm', `${constants.UNKNOWN_ERROR} ${e.message}`); - } - try { - if (passphrase === confirm) { - const { keyAttributes, masterKey } = - await generateKeyAttributes(passphrase); - setData(LS_KEYS.ORIGINAL_KEY_ATTRIBUTES, keyAttributes); - await generateAndSaveIntermediateKeyAttributes( - passphrase, - keyAttributes, - masterKey + try { + setData(LS_KEYS.USER, { email }); + await getOtt(email); + } catch (e) { + setFieldError( + 'confirm', + `${constants.UNKNOWN_ERROR} ${e.message}` ); - - await SaveKeyInSessionStore( - SESSION_KEYS.ENCRYPTION_KEY, - masterKey - ); - setJustSignedUp(true); - router.push(PAGES.VERIFY); - } else { - setFieldError('confirm', constants.PASSPHRASE_MATCH_ERROR); + throw e; } - } catch (e) { - logError(e); - setFieldError('passphrase', constants.PASSWORD_GENERATION_FAILED); + try { + if (passphrase === confirm) { + const { keyAttributes, masterKey } = + await generateKeyAttributes(passphrase); + setData(LS_KEYS.ORIGINAL_KEY_ATTRIBUTES, keyAttributes); + await generateAndSaveIntermediateKeyAttributes( + passphrase, + keyAttributes, + masterKey + ); + + await SaveKeyInSessionStore( + SESSION_KEYS.ENCRYPTION_KEY, + masterKey + ); + setJustSignedUp(true); + router.push(PAGES.VERIFY); + } else { + setFieldError('confirm', constants.PASSPHRASE_MATCH_ERROR); + } + } catch (e) { + setFieldError( + 'passphrase', + constants.PASSWORD_GENERATION_FAILED + ); + throw e; + } + } catch (err) { + logError(err, 'signup failed'); } setLoading(false); }; diff --git a/src/utils/common/errorUtil.ts b/src/utils/common/errorUtil.ts index e357917ed..5e49ffe64 100644 --- a/src/utils/common/errorUtil.ts +++ b/src/utils/common/errorUtil.ts @@ -24,6 +24,7 @@ export enum CustomError { STORAGE_QUOTA_EXCEEDED = 'storage quota exceeded', SESSION_EXPIRED_MESSAGE = 'session expired', TYPE_DETECTION_FAILED = 'type detection failed', + SIGNUP_FAILED = 'signup failed', } function parseUploadError(error: AxiosResponse) { @@ -88,3 +89,24 @@ export function getUserFacingErrorMessage( return constants.UNKNOWN_ERROR; } } + +export function errorWithContext(originalError: Error, context: string) { + const errorWithContext = new Error(context); + errorWithContext.stack = errorWithContext.stack + .split('\n') + .slice(1) + .join('\n'); + console.log(originalError, errorWithContext); + let i = 0; + const errorWithContextStack = errorWithContext.stack.split('\n').reverse(); + const originalErrorStack = originalError.stack.split('\n').reverse(); + const requiredStack: string[] = []; + while (errorWithContextStack[i] === originalErrorStack[i]) { + i++; + } + requiredStack.push(...errorWithContextStack); + requiredStack.push(...originalErrorStack.slice(i + 1)); + requiredStack.reverse(); + errorWithContext.stack = requiredStack.join('\n'); + return errorWithContext; +} diff --git a/src/utils/sentry/index.ts b/src/utils/sentry/index.ts index 02432d718..1ad94df16 100644 --- a/src/utils/sentry/index.ts +++ b/src/utils/sentry/index.ts @@ -1,4 +1,5 @@ import * as Sentry from '@sentry/nextjs'; +import { errorWithContext } from 'utils/common/errorUtil'; import { getUserAnonymizedID } from 'utils/user'; export const logError = ( @@ -6,15 +7,11 @@ export const logError = ( msg?: string, info?: Record ) => { - Sentry.captureException(e, { + const err = errorWithContext(e, msg); + Sentry.captureException(err, { level: Sentry.Severity.Info, user: { id: getUserAnonymizedID() }, contexts: { - ...(msg && { - context: { - message: msg, - }, - }), ...(info && { info: info, }), From 7dfd6658ea267b8bcee19deb0c3be0faf7ae1eca Mon Sep 17 00:00:00 2001 From: Abhinav-grd Date: Wed, 1 Sep 2021 18:04:18 +0530 Subject: [PATCH 3/5] added compulary context message to all logError calls --- src/pages/_app.tsx | 2 +- src/pages/credentials/index.tsx | 5 ++--- src/pages/recover/index.tsx | 2 +- src/pages/two-factor/recover/index.tsx | 2 +- src/services/billingService.ts | 4 ++-- src/services/collectionService.ts | 7 +++---- src/services/exportService.ts | 2 +- src/services/upload/metadataService.ts | 2 +- src/services/upload/thumbnailService.ts | 14 ++++++-------- src/services/upload/uploadHttpClient.ts | 2 +- src/utils/billingUtil.ts | 2 +- src/utils/sentry/index.ts | 2 +- 12 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 856ed81fe..00b11549a 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -472,7 +472,7 @@ export default function App({ Component, err }) { HTTPService.getInterceptors().response.use( (resp) => resp, (error) => { - logError(error); + logError(error, 'Network Error'); return Promise.reject(error); } ); diff --git a/src/pages/credentials/index.tsx b/src/pages/credentials/index.tsx index ec516a145..9b92b07ed 100644 --- a/src/pages/credentials/index.tsx +++ b/src/pages/credentials/index.tsx @@ -57,7 +57,7 @@ export default function Credentials() { keyAttributes.memLimit ); } catch (e) { - console.error('failed to deriveKey ', e.message); + logError(e, 'failed to derive key'); throw e; } try { @@ -78,7 +78,7 @@ export default function Credentials() { router.push(PAGES.GALLERY); } catch (e) { - logError(e); + logError(e, 'user entered a wrong password'); setFieldError('passphrase', constants.INCORRECT_PASSPHRASE); } } catch (e) { @@ -86,7 +86,6 @@ export default function Credentials() { 'passphrase', `${constants.UNKNOWN_ERROR} ${e.message}` ); - console.error('failed to verifyPassphrase ', e.message); } }; diff --git a/src/pages/recover/index.tsx b/src/pages/recover/index.tsx index 95a9f8fa6..898841b08 100644 --- a/src/pages/recover/index.tsx +++ b/src/pages/recover/index.tsx @@ -63,7 +63,7 @@ export default function Recover() { setData(LS_KEYS.SHOW_BACK_BUTTON, { value: false }); router.push(PAGES.CHANGE_PASSWORD); } catch (e) { - logError(e); + logError(e, 'password recovery failed'); setFieldError('passphrase', constants.INCORRECT_RECOVERY_KEY); } }; diff --git a/src/pages/two-factor/recover/index.tsx b/src/pages/two-factor/recover/index.tsx index a79f0182c..ee0219cdd 100644 --- a/src/pages/two-factor/recover/index.tsx +++ b/src/pages/two-factor/recover/index.tsx @@ -65,7 +65,7 @@ export default function Recover() { }); router.push(PAGES.CREDENTIALS); } catch (e) { - logError(e); + logError(e, 'two factor recovery failed'); setFieldError('passphrase', constants.INCORRECT_RECOVERY_KEY); } }; diff --git a/src/services/billingService.ts b/src/services/billingService.ts index 36144c0f6..630dc0f34 100644 --- a/src/services/billingService.ts +++ b/src/services/billingService.ts @@ -107,7 +107,7 @@ class billingService { const { subscription } = response.data; setData(LS_KEYS.SUBSCRIPTION, subscription); } catch (e) { - logError(e); + logError(e, 'subscription cancel failed'); throw e; } } @@ -125,7 +125,7 @@ class billingService { const { subscription } = response.data; setData(LS_KEYS.SUBSCRIPTION, subscription); } catch (e) { - logError(e); + logError(e, 'failed to activate subscription'); throw e; } } diff --git a/src/services/collectionService.ts b/src/services/collectionService.ts index a8cf01ed8..a07ff5669 100644 --- a/src/services/collectionService.ts +++ b/src/services/collectionService.ts @@ -114,10 +114,9 @@ const getCollections = async ( key ); } catch (e) { - logError( - e, - `decryption failed for collection with id=${collection.id}` - ); + logError(e, `decryption failed for collection`, { + collectionID: collection.id, + }); } return collectionWithSecrets; } diff --git a/src/services/exportService.ts b/src/services/exportService.ts index f22023a1f..6f0e69eea 100644 --- a/src/services/exportService.ts +++ b/src/services/exportService.ts @@ -227,7 +227,7 @@ class ExportService { } return { paused: false }; } catch (e) { - logError(e); + logError(e, 'export failed '); } } async addFilesQueuedRecord(folder: string, files: File[]) { diff --git a/src/services/upload/metadataService.ts b/src/services/upload/metadataService.ts index 3beeaed1e..5bfee0906 100644 --- a/src/services/upload/metadataService.ts +++ b/src/services/upload/metadataService.ts @@ -111,7 +111,7 @@ export async function parseMetadataJSON(receivedFile: globalThis.File) { } return { title, parsedMetaDataJSON } as ParsedMetaDataJSONWithTitle; } catch (e) { - logError(e); + logError(e, 'parseMetadataJSON failed'); // ignore } } diff --git a/src/services/upload/thumbnailService.ts b/src/services/upload/thumbnailService.ts index 2867657e4..ab81aa131 100644 --- a/src/services/upload/thumbnailService.ts +++ b/src/services/upload/thumbnailService.ts @@ -1,5 +1,5 @@ import { FILE_TYPE } from 'services/fileService'; -import { CustomError } from 'utils/common/errorUtil'; +import { CustomError, errorWithContext } from 'utils/common/errorUtil'; import { convertHEIC2JPEG } from 'utils/file'; import { logError } from 'utils/sentry'; import { BLACK_THUMBNAIL_BASE64 } from '../../../public/images/black-thumbnail-b64'; @@ -85,13 +85,11 @@ export async function generateImageThumbnail( clearTimeout(timeout); resolve(null); } catch (e) { - reject(e); - logError(e); - reject( - Error( - `${CustomError.THUMBNAIL_GENERATION_FAILED} err: ${e}` - ) + const err = errorWithContext( + e, + `${CustomError.THUMBNAIL_GENERATION_FAILED} err: ${e}` ); + reject(err); } }; timeout = setTimeout( @@ -142,7 +140,7 @@ export async function generateVideoThumbnail(file: globalThis.File) { const err = Error( `${CustomError.THUMBNAIL_GENERATION_FAILED} err: ${e}` ); - logError(err); + logError(e, CustomError.THUMBNAIL_GENERATION_FAILED); reject(err); } }); diff --git a/src/services/upload/uploadHttpClient.ts b/src/services/upload/uploadHttpClient.ts index e6adc8571..a3bc006e5 100644 --- a/src/services/upload/uploadHttpClient.ts +++ b/src/services/upload/uploadHttpClient.ts @@ -123,7 +123,7 @@ class UploadHttpClient { ); if (!resp?.headers?.etag) { const err = Error(CustomError.ETAG_MISSING); - logError(err); + logError(err, 'putFile in parts failed'); throw err; } return resp; diff --git a/src/utils/billingUtil.ts b/src/utils/billingUtil.ts index 4db14260c..555bd9016 100644 --- a/src/utils/billingUtil.ts +++ b/src/utils/billingUtil.ts @@ -230,7 +230,7 @@ function handleFailureReason( setDialogMessage: SetDialogMessage, setLoading: SetLoading ): void { - logError(Error(`subscription purchase failed with reason- ${reason}`)); + logError(Error(reason), 'subscription purchase failed'); switch (reason) { case FAILURE_REASON.CANCELED: setDialogMessage({ diff --git a/src/utils/sentry/index.ts b/src/utils/sentry/index.ts index 1ad94df16..6f1b80f57 100644 --- a/src/utils/sentry/index.ts +++ b/src/utils/sentry/index.ts @@ -4,7 +4,7 @@ import { getUserAnonymizedID } from 'utils/user'; export const logError = ( e: any, - msg?: string, + msg: string, info?: Record ) => { const err = errorWithContext(e, msg); From 7ec132b39f493fc9dc58bcedd8160c68ca470e07 Mon Sep 17 00:00:00 2001 From: Abhinav-grd Date: Wed, 1 Sep 2021 18:08:20 +0530 Subject: [PATCH 4/5] updated the errorWithContext generation logic --- src/utils/common/errorUtil.ts | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/src/utils/common/errorUtil.ts b/src/utils/common/errorUtil.ts index 5e49ffe64..d74a988fd 100644 --- a/src/utils/common/errorUtil.ts +++ b/src/utils/common/errorUtil.ts @@ -92,21 +92,9 @@ export function getUserFacingErrorMessage( export function errorWithContext(originalError: Error, context: string) { const errorWithContext = new Error(context); - errorWithContext.stack = errorWithContext.stack - .split('\n') - .slice(1) - .join('\n'); - console.log(originalError, errorWithContext); - let i = 0; - const errorWithContextStack = errorWithContext.stack.split('\n').reverse(); - const originalErrorStack = originalError.stack.split('\n').reverse(); - const requiredStack: string[] = []; - while (errorWithContextStack[i] === originalErrorStack[i]) { - i++; - } - requiredStack.push(...errorWithContextStack); - requiredStack.push(...originalErrorStack.slice(i + 1)); - requiredStack.reverse(); - errorWithContext.stack = requiredStack.join('\n'); + errorWithContext.stack = + errorWithContext.stack.split('\n').slice(2, 4).join('\n') + + '/n' + + originalError.stack; return errorWithContext; } From baf509085e9b80c5e9d039e5a90e8814e52afcd4 Mon Sep 17 00:00:00 2001 From: Abhinav-grd Date: Thu, 2 Sep 2021 12:20:27 +0530 Subject: [PATCH 5/5] fix new line between error stacks --- src/utils/common/errorUtil.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/common/errorUtil.ts b/src/utils/common/errorUtil.ts index d74a988fd..e5e834319 100644 --- a/src/utils/common/errorUtil.ts +++ b/src/utils/common/errorUtil.ts @@ -94,7 +94,7 @@ export function errorWithContext(originalError: Error, context: string) { const errorWithContext = new Error(context); errorWithContext.stack = errorWithContext.stack.split('\n').slice(2, 4).join('\n') + - '/n' + + '\n' + originalError.stack; return errorWithContext; }