6eaf3c8c92
* feat(workspaces): drop createdByUserId from the dataschema * feat(workspaces): repositories WIP * merge * protect against removing last admin in workspace * quick impl and stub tests * add tests * services * unit tests for role services * feat(workspaces): authorize project creation if workspace specified * feat(workspaces): emit project created event * feat(workspaces): assign roles on project create in workspace * feat(workspaces): update project roles when user added to workspace * feat(workspaces): stencil gql resolvers * fix(workspaces): lol lmao * fix(workspaces): perform automatic project role update in service function * fix(workspaces): also delete roles * fix(workspaces): broke tests again oops * fix(workspaces): update `onProjectCreated` listener to use new repo method * fix(workspaces): use service function in event listener * fix(workspaces): get workspace projects via existing stream repo functions * fix(workspaces): roles mapping in domain, use enum * feat(workspaces): stencil gql api and resolvers * fix(workspaces): repair type reference in tests * fix(workspaces): consolidate files, use different existing stream-getter * fix(workspaces): more specific error * fix(workspaces): roles and scopes * fix(workspaces): yield per page * fix(workspaces): some test dry * fix(workspaces): superdry * fix(workspaces): add scopes * fix(workspaces): classic * feat(workspaces): create workspace mutation * feat(workspaces): I'm sure everything will be fine * fix(workspaces): yep * fix(workspaces): successful gql e2e test * feat(workspaces): update workspace resolver * chore(workspaces): update resolver test * feat(workspaces): some retrieval resolvers * chore(workspaces): tests for query resolvers * fix(chore): revert temp test command change * fix(workspaces): test structure and gql types * fix(workspaces): validate user authz to perform some operations * fix(workspaces): use existing test infrastructure * fix(workspaces): stop `isPublic` check if authorizing a workspace resource * fix(workspaces): better test hygiene --------- Co-authored-by: Gergő Jedlicska <gergo@jedlicska.com>
175 lines
5.2 KiB
TypeScript
175 lines
5.2 KiB
TypeScript
import { Resolvers } from '@/modules/core/graph/generated/graphql'
|
|
import { getFeatureFlags } from '@/modules/shared/helpers/envHelper'
|
|
import {
|
|
WorkspaceNotFoundError,
|
|
WorkspacesNotAuthorizedError,
|
|
WorkspacesNotYetImplementedError
|
|
} from '@/modules/workspaces/errors/workspace'
|
|
import {
|
|
getWorkspaceFactory,
|
|
getWorkspaceRolesForUserFactory,
|
|
upsertWorkspaceFactory,
|
|
upsertWorkspaceRoleFactory
|
|
} from '@/modules/workspaces/repositories/workspaces'
|
|
import {
|
|
createWorkspaceFactory,
|
|
updateWorkspaceFactory
|
|
} from '@/modules/workspaces/services/management'
|
|
import db from '@/db/knex'
|
|
import { getEventBus } from '@/modules/shared/services/eventBus'
|
|
import { getWorkspacesForUserFactory } from '@/modules/workspaces/services/retrieval'
|
|
|
|
const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
|
|
|
export = FF_WORKSPACES_MODULE_ENABLED
|
|
? ({
|
|
Query: {
|
|
workspace: async (_parent, args) => {
|
|
const { id: workspaceId } = args
|
|
|
|
// TODO: Use dataloader
|
|
const workspace = await getWorkspaceFactory({ db })({ workspaceId })
|
|
|
|
if (!workspace) {
|
|
throw new WorkspaceNotFoundError()
|
|
}
|
|
|
|
return workspace
|
|
}
|
|
},
|
|
Mutation: {
|
|
workspaceMutations: () => ({})
|
|
},
|
|
WorkspaceMutations: {
|
|
create: async (_parent, args, context) => {
|
|
const { name, description, logoUrl } = args.input
|
|
|
|
const { emit: emitWorkspaceEvent } = getEventBus()
|
|
|
|
const upsertWorkspace = upsertWorkspaceFactory({ db })
|
|
const upsertWorkspaceRole = upsertWorkspaceRoleFactory({ db })
|
|
// TODO: Integrate with blobstorage
|
|
const storeBlob = async () => ''
|
|
|
|
const createWorkspace = createWorkspaceFactory({
|
|
upsertWorkspace,
|
|
upsertWorkspaceRole,
|
|
emitWorkspaceEvent,
|
|
storeBlob
|
|
})
|
|
|
|
const workspace = await createWorkspace({
|
|
userId: context.userId!,
|
|
workspaceInput: {
|
|
name,
|
|
description: description ?? null,
|
|
logoUrl: logoUrl ?? null
|
|
}
|
|
})
|
|
|
|
return workspace
|
|
},
|
|
delete: async () => {
|
|
throw new WorkspacesNotYetImplementedError()
|
|
},
|
|
update: async (_parent, args, context) => {
|
|
const { id: workspaceId, ...workspaceInput } = args.input
|
|
|
|
const { emit: emitWorkspaceEvent } = getEventBus()
|
|
|
|
const getWorkspace = getWorkspaceFactory({ db })
|
|
const upsertWorkspace = upsertWorkspaceFactory({ db })
|
|
// TODO: Integrate with blobstorage
|
|
const storeBlob = async () => ''
|
|
|
|
const updateWorkspace = updateWorkspaceFactory({
|
|
getWorkspace,
|
|
upsertWorkspace,
|
|
emitWorkspaceEvent,
|
|
storeBlob
|
|
})
|
|
|
|
const workspace = await updateWorkspace({
|
|
workspaceId,
|
|
workspaceInput,
|
|
workspaceUpdaterId: context.userId!
|
|
})
|
|
|
|
return workspace
|
|
},
|
|
updateRole: async () => {
|
|
throw new WorkspacesNotYetImplementedError()
|
|
},
|
|
deleteRole: async () => {
|
|
throw new WorkspacesNotYetImplementedError()
|
|
}
|
|
},
|
|
WorkspaceInviteMutations: {
|
|
create: async () => {
|
|
throw new WorkspacesNotYetImplementedError()
|
|
},
|
|
batchCreate: async () => {
|
|
throw new WorkspacesNotYetImplementedError()
|
|
},
|
|
use: async () => {
|
|
throw new WorkspacesNotYetImplementedError()
|
|
},
|
|
cancel: async () => {
|
|
throw new WorkspacesNotYetImplementedError()
|
|
}
|
|
},
|
|
Workspace: {
|
|
role: async () => {
|
|
// Get user id from parent, get role and return
|
|
throw new WorkspacesNotYetImplementedError()
|
|
},
|
|
team: async () => {
|
|
// Get roles for workspace
|
|
throw new WorkspacesNotYetImplementedError()
|
|
},
|
|
invitedTeam: async () => {
|
|
// Get invites
|
|
throw new WorkspacesNotYetImplementedError()
|
|
},
|
|
projects: async () => {
|
|
// Get projects in workspace
|
|
throw new WorkspacesNotYetImplementedError()
|
|
}
|
|
},
|
|
User: {
|
|
workspaces: async (_parent, _args, context) => {
|
|
if (!context.userId) {
|
|
throw new WorkspacesNotAuthorizedError()
|
|
}
|
|
|
|
const getWorkspace = getWorkspaceFactory({ db })
|
|
const getWorkspaceRolesForUser = getWorkspaceRolesForUserFactory({ db })
|
|
|
|
const getWorkspacesForUser = getWorkspacesForUserFactory({
|
|
getWorkspace,
|
|
getWorkspaceRolesForUser
|
|
})
|
|
|
|
const workspaces = await getWorkspacesForUser({ userId: context.userId })
|
|
|
|
// TODO: Pagination
|
|
return {
|
|
items: workspaces,
|
|
totalCount: workspaces.length
|
|
}
|
|
}
|
|
},
|
|
Project: {
|
|
workspace: async () => {
|
|
// Get workspaceId from project, get and return workspace data
|
|
throw new WorkspacesNotYetImplementedError()
|
|
}
|
|
},
|
|
AdminQueries: {
|
|
workspaceList: async () => {
|
|
throw new WorkspacesNotYetImplementedError()
|
|
}
|
|
}
|
|
} as Resolvers)
|
|
: {}
|