fix(regions): respect region during project move to workspace (#4985)

This commit is contained in:
Chuck Driesler
2025-06-25 12:54:24 +01:00
committed by GitHub
parent 1a0342ad25
commit 2ef38a3962
7 changed files with 112 additions and 10 deletions
@@ -155,7 +155,7 @@ import { getUserFactory, getUsersFactory } from '@/modules/core/repositories/use
import { getServerInfoFactory } from '@/modules/core/repositories/server'
import { asOperation, commandFactory } from '@/modules/shared/command'
import { throwIfRateLimitedFactory } from '@/modules/core/utils/ratelimiter'
import { getRegionDb } from '@/modules/multiregion/utils/dbSelector'
import { getProjectDbClient, getRegionDb } from '@/modules/multiregion/utils/dbSelector'
import {
listUserExpiredSsoSessionsFactory,
listWorkspaceSsoMembershipsByUserEmailFactory
@@ -226,6 +226,7 @@ import {
validateProjectInviteBeforeFinalizationFactory
} from '@/modules/serverinvites/services/coreFinalization'
import { WorkspaceInvitesLimit } from '@/modules/workspaces/domain/constants'
import { copyWorkspaceFactory } from '@/modules/workspaces/repositories/projectRegions'
const eventBus = getEventBus()
const getServerInfo = getServerInfoFactory({ db })
@@ -1539,6 +1540,8 @@ export = FF_WORKSPACES_MODULE_ENABLED
moveToWorkspace: async (_parent, args, context) => {
const { projectId, workspaceId } = args
const projectDb = await getProjectDbClient({ projectId })
const logger = context.log.child({
projectId,
streamId: projectId, //legacy
@@ -1562,9 +1565,13 @@ export = FF_WORKSPACES_MODULE_ENABLED
operationFactory: ({ db, emit }) =>
moveProjectToWorkspaceFactory({
getProject: getProjectFactory({ db }),
updateProject: updateProjectFactory({ db }),
updateProject: updateProjectFactory({ db: projectDb }),
updateProjectRole: updateStreamRoleAndNotify,
getProjectCollaborators: getStreamCollaboratorsFactory({ db }),
copyWorkspace: copyWorkspaceFactory({
sourceDb: db,
targetDb: projectDb
}),
getWorkspaceRolesAndSeats: getWorkspaceRolesAndSeatsFactory({ db }),
updateWorkspaceRole: addOrUpdateWorkspaceRoleFactory({
getWorkspaceRoles: getWorkspaceRolesFactory({ db }),
@@ -7,7 +7,8 @@ import {
IntersectProjectCollaboratorsAndWorkspaceCollaborators,
QueryAllWorkspaceProjects,
AddOrUpdateWorkspaceRole,
ValidateWorkspaceMemberProjectRole
ValidateWorkspaceMemberProjectRole,
CopyWorkspace
} from '@/modules/workspaces/domain/operations'
import {
WorkspaceInvalidProjectError,
@@ -99,6 +100,7 @@ export const moveProjectToWorkspaceFactory =
updateProject,
updateProjectRole,
getProjectCollaborators,
copyWorkspace,
getWorkspaceDomains,
getWorkspaceRolesAndSeats,
updateWorkspaceRole,
@@ -110,6 +112,7 @@ export const moveProjectToWorkspaceFactory =
updateProject: UpdateProject
updateProjectRole: UpdateStreamRole
getProjectCollaborators: GetStreamCollaborators
copyWorkspace: CopyWorkspace
getWorkspaceDomains: GetWorkspaceDomains
getWorkspaceRolesAndSeats: GetWorkspaceRolesAndSeats
updateWorkspaceRole: AddOrUpdateWorkspaceRole
@@ -139,6 +142,9 @@ export const moveProjectToWorkspaceFactory =
])
if (!workspace) throw new WorkspaceNotFoundError()
// Ensure workspace record exists in source region
await copyWorkspace({ workspaceId: workspace.id })
for (const projectMembers of chunk(projectTeam, 5)) {
await Promise.all(
projectMembers.map(async ({ id: userId, streamRole: currentProjectRole }) => {
@@ -30,6 +30,7 @@ import {
MoveProjectToWorkspaceDocument,
ProjectUpdateRoleInput,
ProjectVisibility,
UpdateProjectDocument,
UpdateProjectRoleDocument,
UpdateWorkspaceProjectRoleDocument
} from '@/test/graphql/generated/graphql'
@@ -40,6 +41,7 @@ import {
} from '@/test/graphqlHelper'
import { beforeEachContext } from '@/test/hooks'
import { mockAdminOverride } from '@/test/mocks/global'
import { isMultiRegionTestMode } from '@/test/speckle-helpers/regions'
import {
addToStream,
BasicTestStream,
@@ -860,7 +862,8 @@ describe('Workspace project GQL CRUD', () => {
id: '',
ownerId: '',
name: 'Test Project',
visibility: ProjectRecordVisibility.Private
visibility: ProjectRecordVisibility.Private,
regionKey: isMultiRegionTestMode() ? 'region1' : undefined
}
const targetWorkspace: BasicTestWorkspace = {
@@ -982,6 +985,27 @@ describe('Workspace project GQL CRUD', () => {
expect(resB).to.not.haveGraphQLErrors()
expect(adminWorkspaceRole?.role).to.equal(Roles.Workspace.Admin)
})
it('should respect project region during move mutations @multiregion', async () => {
const resA = await apollo.execute(MoveProjectToWorkspaceDocument, {
projectId: testProject.id,
workspaceId: targetWorkspace.id
})
const resB = await apollo.execute(UpdateProjectDocument, {
input: {
id: testProject.id,
name: 'Foo'
}
})
const resC = await apollo.execute(GetProjectDocument, {
id: testProject.id
})
expect(resA).to.not.haveGraphQLErrors()
expect(resB).to.not.haveGraphQLErrors()
expect(resC).to.not.haveGraphQLErrors()
expect(resC.data?.project?.workspaceId).to.equal(targetWorkspace.id)
})
})
// moved over Alessandro's tests from core to here, since they are all related to workspaces
@@ -245,6 +245,7 @@ describe('Project management services', () => {
getProjectCollaborators: async () => {
expect.fail()
},
copyWorkspace: async () => '',
getWorkspaceRolesAndSeats: async () => {
expect.fail()
},
@@ -290,6 +291,7 @@ describe('Project management services', () => {
getProjectCollaborators: async () => {
expect.fail()
},
copyWorkspace: async () => '',
getWorkspaceRolesAndSeats: async () => {
expect.fail()
},
@@ -344,6 +346,7 @@ describe('Project management services', () => {
} as unknown as ProjectTeamMember
]
},
copyWorkspace: async () => '',
getWorkspaceRolesAndSeats: async () => {
return {
[userId]: {
@@ -413,6 +416,7 @@ describe('Project management services', () => {
} as unknown as ProjectTeamMember
]
},
copyWorkspace: async () => '',
getWorkspaceRolesAndSeats: async () => {
return {}
},
@@ -486,6 +490,7 @@ describe('Project management services', () => {
} as unknown as ProjectTeamMember
]
},
copyWorkspace: async () => '',
getWorkspaceRolesAndSeats: async () => {
return workspaceRole && workspaceSeatType
? {