From 11ce29197bf239f9645aa8df198dd042659fe99d Mon Sep 17 00:00:00 2001 From: Jessica Lawshe <5312836+lawshe@users.noreply.github.com> Date: Thu, 16 Nov 2023 10:17:36 -0600 Subject: [PATCH] Merge pull request #15687 from overleaf/jel-token-v1-mismatch [web] Test for v1 project URL fragment in link sharing hash check GitOrigin-RevId: 10cb2efe60f4613e3a39a5199bd653376c06ad3b --- .../TokenAccess/TokenAccessHandler.js | 18 ++++- .../TokenAccess/TokenAccessHandlerTests.js | 72 +++++++++++++++++-- 2 files changed, 83 insertions(+), 7 deletions(-) diff --git a/services/web/app/src/Features/TokenAccess/TokenAccessHandler.js b/services/web/app/src/Features/TokenAccess/TokenAccessHandler.js index b1ee4483d0..6da0d7f0cf 100644 --- a/services/web/app/src/Features/TokenAccess/TokenAccessHandler.js +++ b/services/web/app/src/Features/TokenAccess/TokenAccessHandler.js @@ -294,20 +294,34 @@ const TokenAccessHandler = { tokenHashPrefix = tokenHashPrefix.replace('#', '').replace('%23', '') } + const v1Format = /%2F[0-9]{7,8}%2F/ + const isSuspectedV1Format = v1Format.test(tokenHashPrefix) + if (!tokenHashPrefix) { hashPrefixStatus = 'missing' } else { const expectedHashPrefix = TokenAccessHandler.createTokenHashPrefix(token) if (expectedHashPrefix === tokenHashPrefix) { hashPrefixStatus = 'match' + } else if (isSuspectedV1Format) { + hashPrefixStatus = 'mismatch-v1-format' } else { hashPrefixStatus = 'mismatch' } } - if (hashPrefixStatus === 'mismatch') { + if ( + hashPrefixStatus === 'mismatch' || + hashPrefixStatus === 'mismatch-v1-format' + ) { logger.info( - { tokenHashPrefix, hashPrefixStatus, userId, ...logData, type }, + { + tokenHashPrefix, + hashPrefixStatus, + userId, + ...logData, + type, + }, 'mismatched token hash prefix' ) } diff --git a/services/web/test/unit/src/TokenAccess/TokenAccessHandlerTests.js b/services/web/test/unit/src/TokenAccess/TokenAccessHandlerTests.js index 9b0a0a3e99..02c4757312 100644 --- a/services/web/test/unit/src/TokenAccess/TokenAccessHandlerTests.js +++ b/services/web/test/unit/src/TokenAccess/TokenAccessHandlerTests.js @@ -661,7 +661,7 @@ describe('TokenAccessHandler', function () { `#${prefix}`, 'readOnly', userId, - projectId + { projectId } ) expect(this.Metrics.inc).to.have.been.calledWith( @@ -707,7 +707,7 @@ describe('TokenAccessHandler', function () { undefined, 'readOnly', userId, - projectId + { projectId } ) expect(this.Metrics.inc).to.have.been.calledWith( @@ -724,7 +724,7 @@ describe('TokenAccessHandler', function () { '#', 'readOnly', userId, - projectId + { projectId } ) expect(this.Metrics.inc).to.have.been.calledWith( @@ -735,7 +735,7 @@ describe('TokenAccessHandler', function () { } ) }) - it('it handles encoded hashtags', function () { + it('handles encoded hashtags', function () { const token = 'zxpxjrwdtsgd' const prefix = this.TokenAccessHandler.createTokenHashPrefix(token) @@ -744,7 +744,7 @@ describe('TokenAccessHandler', function () { `%23${prefix}`, 'readOnly', userId, - projectId + { projectId } ) expect(this.Metrics.inc).to.have.been.calledWith( @@ -755,5 +755,67 @@ describe('TokenAccessHandler', function () { } ) }) + it('sends "mismatch-v1-format" for suspected v1 URLs with 7 numbers in URL fragment', function () { + const token = '4112142489ddsbkrdzhxrq' + const prefix = '%2F1234567%2F' + + this.TokenAccessHandler.checkTokenHashPrefix( + token, + `#${prefix}`, + 'readAndWrite', + userId, + { projectId } + ) + + expect(this.Metrics.inc).to.have.been.calledWith( + 'link-sharing.hash-check', + { + path: 'readAndWrite', + status: 'mismatch-v1-format', + } + ) + + expect(this.logger.info).to.have.been.calledWith( + { + tokenHashPrefix: prefix, + hashPrefixStatus: 'mismatch-v1-format', + userId, + projectId, + type: 'readAndWrite', + }, + 'mismatched token hash prefix' + ) + }) + it('sends "mismatch-v1-format" for suspected v1 URLs with 8 numbers in URL fragment', function () { + const token = '4112142489ddsbkrdzhxrq' + const prefix = '%2F12345678%2F' + + this.TokenAccessHandler.checkTokenHashPrefix( + token, + `#${prefix}`, + 'readAndWrite', + userId, + { projectId } + ) + + expect(this.Metrics.inc).to.have.been.calledWith( + 'link-sharing.hash-check', + { + path: 'readAndWrite', + status: 'mismatch-v1-format', + } + ) + + expect(this.logger.info).to.have.been.calledWith( + { + tokenHashPrefix: prefix, + hashPrefixStatus: 'mismatch-v1-format', + userId, + projectId, + type: 'readAndWrite', + }, + 'mismatched token hash prefix' + ) + }) }) })