From 21444b9d02f6a307a02e7bdb61ba16bb484710ed Mon Sep 17 00:00:00 2001 From: Jakob Ackermann Date: Tue, 13 Jun 2023 09:35:39 +0100 Subject: [PATCH] Merge pull request #13442 from overleaf/jpa-real-time-anonymous-access-tests [real-time] add acceptance tests for token access GitOrigin-RevId: fc0e174021ede19ef911a79a0978fb1db9171156 --- .../test/acceptance/js/ClientTrackingTests.js | 7 +- .../test/acceptance/js/MatrixTests.js | 101 ++++++++++++++---- .../acceptance/js/helpers/FixturesManager.js | 8 +- .../acceptance/js/helpers/MockWebServer.js | 11 +- 4 files changed, 99 insertions(+), 28 deletions(-) diff --git a/services/real-time/test/acceptance/js/ClientTrackingTests.js b/services/real-time/test/acceptance/js/ClientTrackingTests.js index 9ffb09921c..378e33ac29 100644 --- a/services/real-time/test/acceptance/js/ClientTrackingTests.js +++ b/services/real-time/test/acceptance/js/ClientTrackingTests.js @@ -154,10 +154,14 @@ describe('clientTracking', function () { project: { name: 'Test Project' }, publicAccess: 'readAndWrite', }, - (error, { user_id: userId, project_id: projectId }) => { + ( + error, + { user_id: userId, project_id: projectId, anonymousAccessToken } + ) => { if (error) return done(error) this.user_id = userId this.project_id = projectId + this.anonymousAccessToken = anonymousAccessToken return cb() } ) @@ -203,6 +207,7 @@ describe('clientTracking', function () { 'joinProject', { project_id: this.project_id, + anonymousAccessToken: this.anonymousAccessToken, }, cb ) diff --git a/services/real-time/test/acceptance/js/MatrixTests.js b/services/real-time/test/acceptance/js/MatrixTests.js index efb07a06f9..47999f5e0b 100644 --- a/services/real-time/test/acceptance/js/MatrixTests.js +++ b/services/real-time/test/acceptance/js/MatrixTests.js @@ -50,6 +50,7 @@ const async = require('async') const RealTimeClient = require('./helpers/RealTimeClient') const FixturesManager = require('./helpers/FixturesManager') +const MockWebServer = require('./helpers/MockWebServer') const settings = require('@overleaf/settings') const Keys = settings.redis.documentupdater.key_schema @@ -64,12 +65,16 @@ function cleanupPreviousUpdates(docId, cb) { } describe('MatrixTests', function () { - let privateProjectId, privateDocId, readWriteProjectId, readWriteDocId + let privateProjectId, + privateDocId, + readWriteProjectId, + readWriteDocId, + readWriteAnonymousAccessToken let privateClient before(function setupPrivateProject(done) { FixturesManager.setUpEditorSession( - { privilegeLevel: 'owner' }, + { privilegeLevel: 'owner', publicAccessLevel: 'readAndWrite' }, (err, { project_id: projectId, doc_id: docId }) => { if (err) return done(err) privateProjectId = projectId @@ -94,9 +99,10 @@ describe('MatrixTests', function () { { publicAccess: 'readAndWrite', }, - (err, { project_id: projectId, doc_id: docId }) => { + (err, { project_id: projectId, doc_id: docId, anonymousAccessToken }) => { readWriteProjectId = projectId readWriteDocId = docId + readWriteAnonymousAccessToken = anonymousAccessToken done(err) } ) @@ -104,31 +110,19 @@ describe('MatrixTests', function () { const USER_SETUP = { anonymous: { - setup(cb) { - RealTimeClient.setSession({}, err => { - if (err) return cb(err) - cb(null, { - client: RealTimeClient.connect(), - }) - }) + getAnonymousAccessToken() { + return readWriteAnonymousAccessToken }, - }, - - registered: { setup(cb) { - const userId = FixturesManager.getRandomId() RealTimeClient.setSession( { - user: { - _id: userId, - first_name: 'Joe', - last_name: 'Bloggs', + anonTokenAccess: { + [readWriteProjectId]: readWriteAnonymousAccessToken, }, }, err => { if (err) return cb(err) cb(null, { - user_id: userId, client: RealTimeClient.connect(), }) } @@ -136,12 +130,40 @@ describe('MatrixTests', function () { }, }, + registered: { + getAnonymousAccessToken() {}, + setup(cb) { + const userId = FixturesManager.getRandomId() + const user = { _id: userId, first_name: 'Joe', last_name: 'Bloggs' } + RealTimeClient.setSession({ user }, err => { + if (err) return cb(err) + + MockWebServer.inviteUserToProject( + readWriteProjectId, + user, + 'readAndWrite' + ) + cb(null, { + user_id: userId, + client: RealTimeClient.connect(), + }) + }) + }, + }, + registeredWithOwnedProject: { + getAnonymousAccessToken() {}, setup(cb) { FixturesManager.setUpEditorSession( { privilegeLevel: 'owner' }, (err, { project_id: projectId, user_id: userId, doc_id: docId }) => { if (err) return cb(err) + + MockWebServer.inviteUserToProject( + readWriteProjectId, + { _id: userId }, + 'readAndWrite' + ) cb(null, { user_id: userId, project_id: projectId, @@ -169,8 +191,12 @@ describe('MatrixTests', function () { joinReadWriteProject: { getActions(cb) { + const anonymousAccessToken = userItem.getAnonymousAccessToken() cb(null, [ - { rpc: 'joinProject', args: [{ project_id: readWriteProjectId }] }, + { + rpc: 'joinProject', + args: [{ project_id: readWriteProjectId, anonymousAccessToken }], + }, ]) }, needsOwnProject: false, @@ -178,8 +204,12 @@ describe('MatrixTests', function () { joinReadWriteProjectAndDoc: { getActions(cb) { + const anonymousAccessToken = userItem.getAnonymousAccessToken() cb(null, [ - { rpc: 'joinProject', args: [{ project_id: readWriteProjectId }] }, + { + rpc: 'joinProject', + args: [{ project_id: readWriteProjectId, anonymousAccessToken }], + }, { rpc: 'joinDoc', args: [readWriteDocId] }, ]) }, @@ -188,8 +218,12 @@ describe('MatrixTests', function () { joinOwnProject: { getActions(cb) { + const anonymousAccessToken = userItem.getAnonymousAccessToken() cb(null, [ - { rpc: 'joinProject', args: [{ project_id: options.project_id }] }, + { + rpc: 'joinProject', + args: [{ project_id: options.project_id, anonymousAccessToken }], + }, ]) }, needsOwnProject: true, @@ -197,8 +231,12 @@ describe('MatrixTests', function () { joinOwnProjectAndDoc: { getActions(cb) { + const anonymousAccessToken = userItem.getAnonymousAccessToken() cb(null, [ - { rpc: 'joinProject', args: [{ project_id: options.project_id }] }, + { + rpc: 'joinProject', + args: [{ project_id: options.project_id, anonymousAccessToken }], + }, { rpc: 'joinDoc', args: [options.doc_id] }, ]) }, @@ -252,6 +290,23 @@ describe('MatrixTests', function () { }, }, + joinProjectWithBadAccessToken: { + getActions(cb) { + cb(null, [ + { + rpc: 'joinProject', + args: [ + { + project_id: privateProjectId, + anonymousAccessToken: 'invalid-access-token', + }, + ], + fails: 1, + }, + ]) + }, + }, + joinProjectWithDocId: { getActions(cb) { cb(null, [ diff --git a/services/real-time/test/acceptance/js/helpers/FixturesManager.js b/services/real-time/test/acceptance/js/helpers/FixturesManager.js index 9bc8dd67c0..2e565e76a2 100644 --- a/services/real-time/test/acceptance/js/helpers/FixturesManager.js +++ b/services/real-time/test/acceptance/js/helpers/FixturesManager.js @@ -28,19 +28,22 @@ module.exports = FixturesManager = { if (!options.project) { options.project = { name: 'Test Project' } } - const { + let { project_id: projectId, user_id: userId, privilegeLevel, project, publicAccess, userMetadata, + anonymousAccessToken, } = options const privileges = {} privileges[userId] = privilegeLevel if (publicAccess) { - privileges['anonymous-user'] = publicAccess + anonymousAccessToken = + anonymousAccessToken || FixturesManager.getRandomId() + privileges[anonymousAccessToken] = publicAccess } const metadataByUser = {} @@ -73,6 +76,7 @@ module.exports = FixturesManager = { user_id: userId, privilegeLevel, project, + anonymousAccessToken, }) } ) diff --git a/services/real-time/test/acceptance/js/helpers/MockWebServer.js b/services/real-time/test/acceptance/js/helpers/MockWebServer.js index 0994ad71d9..c1ee0e9282 100644 --- a/services/real-time/test/acceptance/js/helpers/MockWebServer.js +++ b/services/real-time/test/acceptance/js/helpers/MockWebServer.js @@ -24,14 +24,19 @@ module.exports = MockWebServer = { return (MockWebServer.projects[projectId] = project) }, - joinProject(projectId, userId, callback) { + inviteUserToProject(projectId, user, privileges) { + MockWebServer.privileges[projectId][user._id] = privileges + MockWebServer.userMetadata[projectId][user._id] = user + }, + + joinProject(projectId, userId, anonymousAccessToken, callback) { if (callback == null) { callback = function () {} } const project = MockWebServer.projects[projectId] const privilegeLevel = MockWebServer.privileges[projectId][userId] || - MockWebServer.privileges[projectId]['anonymous-user'] + MockWebServer.privileges[projectId][anonymousAccessToken] const userMetadata = MockWebServer.userMetadata[projectId]?.[userId] if (privilegeLevel === 'owner') { project.owner = { _id: userId } @@ -44,6 +49,7 @@ module.exports = MockWebServer = { joinProjectRequest(req, res, next) { const { project_id: projectId } = req.params const { user_id: userId } = req.query + const { 'x-sl-anonymous-access-token': anonymousAccessToken } = req.headers if (projectId === '404404404404404404404404') { // not-found return res.status(404).send() @@ -59,6 +65,7 @@ module.exports = MockWebServer = { return MockWebServer.joinProject( projectId, userId, + anonymousAccessToken, (error, project, privilegeLevel, userMetadata) => { if (error != null) { return next(error)