diff --git a/packages/server/modules/workspaces/repositories/workspaces.ts b/packages/server/modules/workspaces/repositories/workspaces.ts index 8741096b08..6adb2c56c8 100644 --- a/packages/server/modules/workspaces/repositories/workspaces.ts +++ b/packages/server/modules/workspaces/repositories/workspaces.ts @@ -2,6 +2,7 @@ import { Workspace, WorkspaceAcl, WorkspaceDomain, + WorkspaceJoinRequest, WorkspaceWithOptionalRole } from '@/modules/workspacesCore/domain/types' import { @@ -67,7 +68,9 @@ const tables = { workspaceDomains: (db: Knex) => db('workspace_domains'), workspacesAcl: (db: Knex) => db('workspace_acl'), workspaceCreationState: (db: Knex) => - db('workspace_creation_state') + db('workspace_creation_state'), + workspaceJoinRequests: (db: Knex) => + db('workspace_join_requests') } export const getUserDiscoverableWorkspacesFactory = @@ -93,6 +96,16 @@ export const getUserDiscoverableWorkspacesFactory = 'acl.workspaceId', 'workspaces.id' ) + .leftJoin( + tables + .workspaceJoinRequests(db) + .select('*') + .where({ userId }) + .as('joinRequest'), + 'joinRequest.workspaceId', + 'workspaces.id' + ) + .whereNull('joinRequest.workspaceId') .whereIn('domain', domains) .where('discoverabilityEnabled', true) .where('verified', true) diff --git a/packages/server/modules/workspaces/tests/integration/repositories.spec.ts b/packages/server/modules/workspaces/tests/integration/repositories.spec.ts index 4e6b2201b2..d6fadbca78 100644 --- a/packages/server/modules/workspaces/tests/integration/repositories.spec.ts +++ b/packages/server/modules/workspaces/tests/integration/repositories.spec.ts @@ -43,6 +43,7 @@ import { } from '@/modules/core/repositories/streams' import { omit } from 'lodash' import { createAndStoreTestWorkspaceFactory } from '@/test/speckle-helpers/workspaces' +import { WorkspaceJoinRequests } from '@/modules/workspacesCore/helpers/db' const getWorkspace = getWorkspaceFactory({ db }) const getWorkspaceBySlug = getWorkspaceBySlugFactory({ db }) @@ -771,6 +772,85 @@ describe('Workspace repositories', () => { expect(workspaces.length).to.equal(1) }) + + it('should not return discoverable workspaces with existing requests for the user', async () => { + const user = await createAndStoreTestUser() + await updateUserEmail({ + query: { + email: user.email + }, + update: { + verified: true + } + }) + const otherUser = await createAndStoreTestUser() + await updateUserEmail({ + query: { + email: otherUser.email + }, + update: { + verified: true + } + }) + + const workspace = await createAndStoreTestWorkspace({ + discoverabilityEnabled: true + }) + await storeWorkspaceDomain({ + workspaceDomain: { + id: cryptoRandomString({ length: 6 }), + domain: 'example.org', + workspaceId: workspace.id, + verified: true, + createdAt: new Date(), + updatedAt: new Date(), + createdByUserId: user.id + } + }) + // existing request for other user + await db(WorkspaceJoinRequests.name).insert({ + workspaceId: workspace.id, + userId: otherUser.id, + createdAt: new Date(), + status: 'pending' + }) + const workspaceWithExistingRequest = await createAndStoreTestWorkspace({ + discoverabilityEnabled: true + }) + await storeWorkspaceDomain({ + workspaceDomain: { + id: cryptoRandomString({ length: 6 }), + domain: 'example.org', + workspaceId: workspaceWithExistingRequest.id, + verified: true, + createdAt: new Date(), + updatedAt: new Date(), + createdByUserId: user.id + } + }) + await db(WorkspaceJoinRequests.name).insert({ + workspaceId: workspaceWithExistingRequest.id, + userId: user.id, + createdAt: new Date(), + status: 'pending' + }) + + const workspaces = await getUserDiscoverableWorkspaces({ + domains: ['example.org'], + userId: user.id + }) + + expect(workspaces.length).to.equal(1) + expect(workspaces[0].id).to.equal(workspace.id) + + const otherUserWorkspaces = await getUserDiscoverableWorkspaces({ + domains: ['example.org'], + userId: otherUser.id + }) + + expect(otherUserWorkspaces.length).to.equal(1) + expect(otherUserWorkspaces[0].id).to.equal(workspaceWithExistingRequest.id) + }) }) describe('getWorkspaceDomainsFactory creates a function, that', () => {