fix(workspaces): add filtering to workspace team query (#2586)
* chore(workspaces): add some tests for new filters * fix(workspaces): args style
This commit is contained in:
@@ -35,15 +35,23 @@ export type DeleteWorkspace = (args: DeleteWorkspaceArgs) => Promise<void>
|
||||
|
||||
/** Workspace Roles */
|
||||
|
||||
export type GetWorkspaceCollaborators = (args: {
|
||||
type GetWorkspaceCollaboratorsArgs = {
|
||||
workspaceId: string
|
||||
/**
|
||||
* Optionally filter by role
|
||||
*/
|
||||
role?: WorkspaceRoles
|
||||
}) => Promise<
|
||||
Array<UserWithRole<LimitedUserRecord> & { workspaceRole: WorkspaceRoles }>
|
||||
>
|
||||
filter?: {
|
||||
/**
|
||||
* Optionally filter by workspace role
|
||||
*/
|
||||
role?: string
|
||||
/**
|
||||
* Optionally filter by user name or email
|
||||
*/
|
||||
search?: string
|
||||
}
|
||||
}
|
||||
|
||||
export type GetWorkspaceCollaborators = (
|
||||
args: GetWorkspaceCollaboratorsArgs
|
||||
) => Promise<Array<UserWithRole<LimitedUserRecord> & { workspaceRole: WorkspaceRoles }>>
|
||||
|
||||
type DeleteWorkspaceRoleArgs = {
|
||||
workspaceId: string
|
||||
|
||||
@@ -72,7 +72,7 @@ import {
|
||||
queryAllWorkspaceProjectsFactory
|
||||
} from '@/modules/workspaces/services/projects'
|
||||
import { getWorkspacesForUserFactory } from '@/modules/workspaces/services/retrieval'
|
||||
import { Roles, WorkspaceRoles } from '@speckle/shared'
|
||||
import { Roles, WorkspaceRoles, removeNullOrUndefinedKeys } from '@speckle/shared'
|
||||
import { chunk } from 'lodash'
|
||||
import { deleteStream } from '@/modules/core/repositories/streams'
|
||||
|
||||
@@ -426,10 +426,11 @@ export = FF_WORKSPACES_MODULE_ENABLED
|
||||
const workspace = await ctx.loaders.workspaces!.getWorkspace.load(parent.id)
|
||||
return workspace?.role || null
|
||||
},
|
||||
team: async (parent) => {
|
||||
team: async (parent, args) => {
|
||||
const getTeam = getWorkspaceCollaboratorsFactory({ db })
|
||||
const collaborators = await getTeam({
|
||||
workspaceId: parent.id
|
||||
workspaceId: parent.id,
|
||||
filter: removeNullOrUndefinedKeys(args?.filter ?? {})
|
||||
})
|
||||
|
||||
return collaborators
|
||||
|
||||
@@ -168,9 +168,7 @@ export const upsertWorkspaceRoleFactory =
|
||||
|
||||
export const getWorkspaceCollaboratorsFactory =
|
||||
({ db }: { db: Knex }): GetWorkspaceCollaborators =>
|
||||
async (params: { workspaceId: string; role?: WorkspaceRoles }) => {
|
||||
const { workspaceId, role } = params
|
||||
|
||||
async ({ workspaceId, filter = {} }) => {
|
||||
const query = DbWorkspaceAcl.knex(db)
|
||||
.select<Array<UserWithRole & { workspaceRole: WorkspaceRoles }>>([
|
||||
...Users.cols,
|
||||
@@ -182,6 +180,14 @@ export const getWorkspaceCollaboratorsFactory =
|
||||
.innerJoin(ServerAcl.name, ServerAcl.col.userId, Users.col.id)
|
||||
.groupBy(Users.col.id, DbWorkspaceAcl.col.role)
|
||||
|
||||
const { search, role } = filter || {}
|
||||
|
||||
if (search) {
|
||||
query
|
||||
.where(Users.col.name, 'ILIKE', `%${search}%`)
|
||||
.orWhere(Users.col.email, 'ILIKE', `%${search}%`)
|
||||
}
|
||||
|
||||
if (role) {
|
||||
query.andWhere(DbWorkspaceAcl.col.role, role)
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@ import {
|
||||
DeleteWorkspaceDocument,
|
||||
GetActiveUserWorkspacesDocument,
|
||||
GetWorkspaceDocument,
|
||||
GetWorkspaceTeamDocument,
|
||||
UpdateWorkspaceDocument,
|
||||
ActiveUserLeaveWorkspaceDocument,
|
||||
UpdateWorkspaceRoleDocument
|
||||
UpdateWorkspaceRoleDocument,
|
||||
ActiveUserLeaveWorkspaceDocument
|
||||
} from '@/test/graphql/generated/graphql'
|
||||
import { Workspace } from '@/modules/workspacesCore/domain/types'
|
||||
import { beforeEachContext } from '@/test/hooks'
|
||||
import { AllScopes } from '@/modules/core/helpers/mainConstants'
|
||||
import {
|
||||
@@ -66,29 +66,35 @@ describe('Workspaces GQL CRUD', () => {
|
||||
})
|
||||
|
||||
describe('retrieval operations', () => {
|
||||
const workspaceIds: string[] = []
|
||||
const workspace: BasicTestWorkspace = {
|
||||
id: '',
|
||||
ownerId: '',
|
||||
name: 'Workspace A'
|
||||
}
|
||||
|
||||
const testMemberUser: BasicTestUser = {
|
||||
id: '',
|
||||
name: 'Jimmy Speckle',
|
||||
email: 'jimmy-speckle@example.org'
|
||||
}
|
||||
|
||||
before(async () => {
|
||||
const workspaces: Pick<Workspace, 'name'>[] = [
|
||||
{ name: 'Workspace A' },
|
||||
{ name: 'Workspace B' }
|
||||
]
|
||||
await createTestWorkspace(workspace, testUser)
|
||||
await createTestUser(testMemberUser)
|
||||
|
||||
const results = await Promise.all(
|
||||
workspaces.map((workspace) =>
|
||||
apollo.execute(CreateWorkspaceDocument, { input: workspace })
|
||||
)
|
||||
)
|
||||
|
||||
for (const result of results) {
|
||||
workspaceIds.push(result.data!.workspaceMutations.create.id)
|
||||
}
|
||||
await apollo.execute(UpdateWorkspaceRoleDocument, {
|
||||
input: {
|
||||
userId: testMemberUser.id,
|
||||
workspaceId: workspace.id,
|
||||
role: Roles.Workspace.Member
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('query workspace', () => {
|
||||
it('should return a workspace that exists', async () => {
|
||||
const res = await apollo.execute(GetWorkspaceDocument, {
|
||||
workspaceId: workspaceIds[0]
|
||||
workspaceId: workspace.id
|
||||
})
|
||||
|
||||
expect(res).to.not.haveGraphQLErrors()
|
||||
@@ -103,12 +109,46 @@ describe('Workspaces GQL CRUD', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('query workspace.team', () => {
|
||||
it('should return workspace members', async () => {
|
||||
const res = await apollo.execute(GetWorkspaceTeamDocument, {
|
||||
workspaceId: workspace.id
|
||||
})
|
||||
|
||||
expect(res).to.not.haveGraphQLErrors()
|
||||
expect(res.data?.workspace.team.length).to.equal(2)
|
||||
})
|
||||
|
||||
it('should respect search filters', async () => {
|
||||
const res = await apollo.execute(GetWorkspaceTeamDocument, {
|
||||
workspaceId: workspace.id,
|
||||
filter: {
|
||||
search: 'jimmy'
|
||||
}
|
||||
})
|
||||
|
||||
expect(res).to.not.haveGraphQLErrors()
|
||||
expect(res.data?.workspace.team.length).to.equal(1)
|
||||
})
|
||||
|
||||
it('should respect role filters', async () => {
|
||||
const res = await apollo.execute(GetWorkspaceTeamDocument, {
|
||||
workspaceId: workspace.id,
|
||||
filter: {
|
||||
role: 'workspace:member'
|
||||
}
|
||||
})
|
||||
|
||||
expect(res).to.not.haveGraphQLErrors()
|
||||
expect(res.data?.workspace.team.length).to.equal(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('query activeUser.workspaces', () => {
|
||||
it('should return all workspaces for a user', async () => {
|
||||
const res = await apollo.execute(GetActiveUserWorkspacesDocument, {})
|
||||
|
||||
expect(res).to.not.haveGraphQLErrors()
|
||||
expect(res.data?.activeUser?.workspaces?.items?.length).to.above(1)
|
||||
expect(res.data?.activeUser?.workspaces?.items?.length).to.equal(1)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user