fix(fe2): not being able to remove member from workspace (#4468)
* fix(fe2): not being able to remove member from workspace * minor comment * withTransaction refactor
This commit is contained in:
committed by
GitHub
parent
c33052e697
commit
0cc19dbdf5
@@ -264,7 +264,7 @@ export const useSettingsMembersActions = (params: {
|
||||
footerItems.push({
|
||||
title: 'Remove from workspace...',
|
||||
id: WorkspaceUserActionTypes.RemoveFromWorkspace,
|
||||
disabled: isOnlyAdmin.value,
|
||||
disabled: isOnlyAdmin.value && targetUserRole.value === Roles.Workspace.Admin,
|
||||
disabledTooltip: 'There must be at least one admin in this workspace'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -120,33 +120,31 @@ export const getBillingRouter = (): Router => {
|
||||
})
|
||||
logger.info(OperationStatus.start, '[{operationName} ({operationStatus})] ')
|
||||
|
||||
// this must use a transaction
|
||||
|
||||
const trx = await db.transaction()
|
||||
|
||||
const completeCheckout = completeCheckoutSessionFactory({
|
||||
getCheckoutSession: getCheckoutSessionFactory({ db: trx }),
|
||||
updateCheckoutSessionStatus: updateCheckoutSessionStatusFactory({
|
||||
db: trx
|
||||
}),
|
||||
upsertPaidWorkspacePlan: upsertPaidWorkspacePlanFactory({ db: trx }),
|
||||
upsertWorkspaceSubscription: upsertWorkspaceSubscriptionFactory({
|
||||
db: trx
|
||||
}),
|
||||
getSubscriptionData: getSubscriptionDataFactory({
|
||||
stripe
|
||||
}),
|
||||
emitEvent: getEventBus().emit
|
||||
})
|
||||
|
||||
await withOperationLogging(
|
||||
async () =>
|
||||
await withTransaction(
|
||||
completeCheckout({
|
||||
sessionId: session.id,
|
||||
subscriptionId
|
||||
}),
|
||||
trx
|
||||
async ({ db }) => {
|
||||
const completeCheckout = completeCheckoutSessionFactory({
|
||||
getCheckoutSession: getCheckoutSessionFactory({ db }),
|
||||
updateCheckoutSessionStatus: updateCheckoutSessionStatusFactory({
|
||||
db
|
||||
}),
|
||||
upsertPaidWorkspacePlan: upsertPaidWorkspacePlanFactory({ db }),
|
||||
upsertWorkspaceSubscription: upsertWorkspaceSubscriptionFactory({
|
||||
db
|
||||
}),
|
||||
getSubscriptionData: getSubscriptionDataFactory({
|
||||
stripe
|
||||
}),
|
||||
emitEvent: getEventBus().emit
|
||||
})
|
||||
|
||||
return completeCheckout({
|
||||
sessionId: session.id,
|
||||
subscriptionId
|
||||
})
|
||||
},
|
||||
{ db }
|
||||
),
|
||||
{
|
||||
logger,
|
||||
|
||||
@@ -23,9 +23,7 @@ import { reconcileWorkspaceSubscriptionFactory } from '@/modules/gatekeeper/clie
|
||||
import Stripe from 'stripe'
|
||||
import { cloneDeep } from 'lodash'
|
||||
import { Logger } from '@/observability/logging'
|
||||
|
||||
// get all workspace plan from the DB
|
||||
// foreach workspace:
|
||||
import { withTransaction } from '@/modules/shared/helpers/dbHelper'
|
||||
|
||||
export const migrateOldWorkspacePlans =
|
||||
({ db, stripe, logger }: { db: Knex; stripe: Stripe; logger: Logger }) =>
|
||||
@@ -52,9 +50,14 @@ export const migrateOldWorkspacePlans =
|
||||
|
||||
for (const oldPlan of oldPlanWorkspaces) {
|
||||
try {
|
||||
await migrateWorkspacePlan({ db, stripe, logger })({
|
||||
workspaceId: oldPlan.workspaceId
|
||||
})
|
||||
await withTransaction(
|
||||
async ({ db }) => {
|
||||
await migrateWorkspacePlan({ db, stripe, logger })({
|
||||
workspaceId: oldPlan.workspaceId
|
||||
})
|
||||
},
|
||||
{ db }
|
||||
)
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
{ err, workspaceId: oldPlan.workspaceId, oldPlan },
|
||||
@@ -166,10 +169,9 @@ export const migrateWorkspacePlan =
|
||||
'Migrating {workspaceId} from old plan {workspacePlan} to new plan {newTargetPlan}'
|
||||
)
|
||||
|
||||
const trx = await db.transaction()
|
||||
// add editor seats to everyone
|
||||
|
||||
const workspaceMembers = await getWorkspaceRolesFactory({ db: trx })({
|
||||
const workspaceMembers = await getWorkspaceRolesFactory({ db })({
|
||||
workspaceId
|
||||
})
|
||||
const seats = workspaceMembers.map((m) => ({
|
||||
@@ -184,7 +186,7 @@ export const migrateWorkspacePlan =
|
||||
'Inserting {migratedSeatsCount} new seats for the workspace {workspaceId}'
|
||||
)
|
||||
|
||||
await trx<WorkspaceSeat>('workspace_seats')
|
||||
await db<WorkspaceSeat>('workspace_seats')
|
||||
.insert(seats)
|
||||
.onConflict(['workspaceId', 'userId'])
|
||||
.merge()
|
||||
@@ -193,7 +195,7 @@ export const migrateWorkspacePlan =
|
||||
{ migratedSeatsCount: seats.length },
|
||||
'Workspace {workspaceId} has added {migratedSeatsCount} seats'
|
||||
)
|
||||
await upsertWorkspacePlanFactory({ db: trx })({
|
||||
await upsertWorkspacePlanFactory({ db })({
|
||||
//@ts-expect-error the switch above makes sure things are ok
|
||||
workspacePlan: {
|
||||
workspaceId,
|
||||
@@ -220,7 +222,7 @@ export const migrateWorkspacePlan =
|
||||
)
|
||||
}
|
||||
// if stripe paid plan, convert the stripe sub to use all editor seats
|
||||
const workspaceSubscription = await getWorkspaceSubscriptionFactory({ db: trx })({
|
||||
const workspaceSubscription = await getWorkspaceSubscriptionFactory({ db })({
|
||||
workspaceId
|
||||
})
|
||||
if (!workspaceSubscription)
|
||||
@@ -264,7 +266,6 @@ export const migrateWorkspacePlan =
|
||||
prorationBehavior: 'create_prorations'
|
||||
})
|
||||
}
|
||||
await trx.commit()
|
||||
log.info('🥳 Workspace plan migration completed for workspace {workspaceId}')
|
||||
|
||||
// add and editor seat to all workspace members
|
||||
|
||||
@@ -147,53 +147,87 @@ export const startQueue = async () => {
|
||||
|
||||
const sourceDb = await getProjectDbClient({ projectId })
|
||||
const sourceObjectStorage = await getProjectObjectStorage({ projectId })
|
||||
const targetDb = await (await getRegionDb({ regionKey })).transaction()
|
||||
const targetDb = await getRegionDb({ regionKey })
|
||||
const targetObjectStorage = await getRegionObjectStorage({ regionKey })
|
||||
|
||||
const updateProjectRegion = updateProjectRegionFactory({
|
||||
getProject: getProjectFactory({ db: sourceDb }),
|
||||
getAvailableRegions: getAvailableRegionsFactory({
|
||||
getRegions: getRegionsFactory({ db }),
|
||||
canWorkspaceUseRegions: canWorkspaceUseRegionsFactory({
|
||||
getWorkspacePlan: getWorkspacePlanFactory({ db })
|
||||
})
|
||||
}),
|
||||
copyWorkspace: copyWorkspaceFactory({ sourceDb, targetDb }),
|
||||
copyProjects: copyProjectsFactory({ sourceDb, targetDb }),
|
||||
copyProjectModels: copyProjectModelsFactory({ sourceDb, targetDb }),
|
||||
copyProjectVersions: copyProjectVersionsFactory({ sourceDb, targetDb }),
|
||||
copyProjectObjects: copyProjectObjectsFactory({ sourceDb, targetDb }),
|
||||
copyProjectAutomations: copyProjectAutomationsFactory({ sourceDb, targetDb }),
|
||||
copyProjectComments: copyProjectCommentsFactory({ sourceDb, targetDb }),
|
||||
copyProjectWebhooks: copyProjectWebhooksFactory({ sourceDb, targetDb }),
|
||||
copyProjectBlobs: copyProjectBlobs({
|
||||
sourceDb,
|
||||
sourceObjectStorage,
|
||||
targetDb,
|
||||
targetObjectStorage
|
||||
}),
|
||||
validateProjectRegionCopy: validateProjectRegionCopyFactory({
|
||||
countProjectModels: getStreamBranchCountFactory({ db: sourceDb }),
|
||||
countProjectVersions: getStreamCommitCountFactory({ db: sourceDb }),
|
||||
countProjectObjects: getStreamObjectCountFactory({ db: sourceDb }),
|
||||
countProjectAutomations: getProjectAutomationsTotalCountFactory({
|
||||
db: sourceDb
|
||||
}),
|
||||
countProjectComments: getStreamCommentCountFactory({ db: sourceDb }),
|
||||
getProjectWebhooks: getStreamWebhooksFactory({ db: sourceDb })
|
||||
}),
|
||||
updateProjectRegionKey: updateProjectRegionKeyFactory({
|
||||
upsertProjectRegionKey: upsertProjectRegionKeyFactory({ db }),
|
||||
cacheDeleteRegionKey: deleteRegionKeyFromCacheFactory({
|
||||
redis: getGenericRedis()
|
||||
}),
|
||||
emitEvent: getEventBus().emit
|
||||
})
|
||||
})
|
||||
|
||||
return await withTransaction(
|
||||
updateProjectRegion({ projectId, regionKey }),
|
||||
targetDb
|
||||
async ({ db: targetDbTrx }) => {
|
||||
const updateProjectRegion = updateProjectRegionFactory({
|
||||
getProject: getProjectFactory({ db: sourceDb }),
|
||||
getAvailableRegions: getAvailableRegionsFactory({
|
||||
getRegions: getRegionsFactory({ db }),
|
||||
canWorkspaceUseRegions: canWorkspaceUseRegionsFactory({
|
||||
getWorkspacePlan: getWorkspacePlanFactory({ db })
|
||||
})
|
||||
}),
|
||||
copyWorkspace: copyWorkspaceFactory({
|
||||
sourceDb,
|
||||
targetDb: targetDbTrx
|
||||
}),
|
||||
copyProjects: copyProjectsFactory({
|
||||
sourceDb,
|
||||
targetDb: targetDbTrx
|
||||
}),
|
||||
copyProjectModels: copyProjectModelsFactory({
|
||||
sourceDb,
|
||||
targetDb: targetDbTrx
|
||||
}),
|
||||
copyProjectVersions: copyProjectVersionsFactory({
|
||||
sourceDb,
|
||||
targetDb: targetDbTrx
|
||||
}),
|
||||
copyProjectObjects: copyProjectObjectsFactory({
|
||||
sourceDb,
|
||||
targetDb: targetDbTrx
|
||||
}),
|
||||
copyProjectAutomations: copyProjectAutomationsFactory({
|
||||
sourceDb,
|
||||
targetDb: targetDbTrx
|
||||
}),
|
||||
copyProjectComments: copyProjectCommentsFactory({
|
||||
sourceDb,
|
||||
targetDb: targetDbTrx
|
||||
}),
|
||||
copyProjectWebhooks: copyProjectWebhooksFactory({
|
||||
sourceDb,
|
||||
targetDb: targetDbTrx
|
||||
}),
|
||||
copyProjectBlobs: copyProjectBlobs({
|
||||
sourceDb,
|
||||
sourceObjectStorage,
|
||||
targetDb: targetDbTrx,
|
||||
targetObjectStorage
|
||||
}),
|
||||
validateProjectRegionCopy: validateProjectRegionCopyFactory({
|
||||
countProjectModels: getStreamBranchCountFactory({
|
||||
db: sourceDb
|
||||
}),
|
||||
countProjectVersions: getStreamCommitCountFactory({
|
||||
db: sourceDb
|
||||
}),
|
||||
countProjectObjects: getStreamObjectCountFactory({
|
||||
db: sourceDb
|
||||
}),
|
||||
countProjectAutomations: getProjectAutomationsTotalCountFactory({
|
||||
db: sourceDb
|
||||
}),
|
||||
countProjectComments: getStreamCommentCountFactory({
|
||||
db: sourceDb
|
||||
}),
|
||||
getProjectWebhooks: getStreamWebhooksFactory({ db: sourceDb })
|
||||
}),
|
||||
updateProjectRegionKey: updateProjectRegionKeyFactory({
|
||||
upsertProjectRegionKey: upsertProjectRegionKeyFactory({ db }),
|
||||
cacheDeleteRegionKey: deleteRegionKeyFromCacheFactory({
|
||||
redis: getGenericRedis()
|
||||
}),
|
||||
emitEvent: getEventBus().emit
|
||||
})
|
||||
})
|
||||
|
||||
return updateProjectRegion({ projectId, regionKey })
|
||||
},
|
||||
{ db: targetDb }
|
||||
)
|
||||
}
|
||||
case 'delete-project-region-data':
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import { EmitArg, EventBus, EventBusEmit } from '@/modules/shared/services/eventBus'
|
||||
import { Knex } from 'knex'
|
||||
|
||||
/**
|
||||
* TODO: Fix api - make operationFactory db arg actually return the trx. Currently many usages of this
|
||||
* are not working correctly cause they just use the db, skipping the transaction
|
||||
*
|
||||
* Also: withOperationLogging and withOperationTransaction could all be merged into this, with
|
||||
* this having a better name like `operationFactory`
|
||||
*/
|
||||
export const commandFactory =
|
||||
<TOperation extends (...args: Parameters<TOperation>) => ReturnType<TOperation>>({
|
||||
db,
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Knex } from 'knex'
|
||||
import { isString } from 'lodash'
|
||||
import { postgresMaxConnections } from '@/modules/shared/helpers/envHelper'
|
||||
import { EnvironmentResourceError } from '@/modules/shared/errors'
|
||||
import { isNonNullable } from '@speckle/shared'
|
||||
import { isNonNullable, MaybeAsync } from '@speckle/shared'
|
||||
|
||||
export type BatchedSelectOptions = {
|
||||
/**
|
||||
@@ -107,17 +107,20 @@ export const numberOfFreeConnections = (knex: Knex) => {
|
||||
}
|
||||
|
||||
export const withTransaction = async <T>(
|
||||
callback: Promise<T> | T,
|
||||
trx: Knex.Transaction
|
||||
): Promise<T> => {
|
||||
operation: (args: { db: Knex }) => MaybeAsync<T>,
|
||||
params: {
|
||||
db: Knex
|
||||
}
|
||||
) => {
|
||||
const { db } = params
|
||||
const trx = await db.transaction()
|
||||
|
||||
try {
|
||||
return await callback
|
||||
const result = await operation({ db: trx })
|
||||
await trx.commit()
|
||||
return result
|
||||
} catch (e) {
|
||||
await trx.rollback()
|
||||
throw e
|
||||
} finally {
|
||||
if (trx.isTransaction && !trx.isCompleted()) {
|
||||
await trx.commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,60 +711,87 @@ export const initializeEventListenersFactory =
|
||||
})
|
||||
}),
|
||||
eventBus.listen(WorkspaceEvents.RoleDeleted, async ({ payload }) => {
|
||||
const trx = await db.transaction()
|
||||
const onWorkspaceRoleDeleted = onWorkspaceRoleDeletedFactory({
|
||||
queryAllWorkspaceProjects: queryAllWorkspaceProjectsFactory({ getStreams }),
|
||||
deleteProjectRole: deleteProjectRoleFactory({ db: trx }),
|
||||
deleteWorkspaceSeat: deleteWorkspaceSeatFactory({ db: trx })
|
||||
})
|
||||
await withTransaction(onWorkspaceRoleDeleted(payload.acl), trx)
|
||||
await withTransaction(
|
||||
async ({ db: trx }) => {
|
||||
const onWorkspaceRoleDeleted = onWorkspaceRoleDeletedFactory({
|
||||
queryAllWorkspaceProjects: queryAllWorkspaceProjectsFactory({
|
||||
getStreams
|
||||
}),
|
||||
deleteProjectRole: deleteProjectRoleFactory({ db: trx }),
|
||||
deleteWorkspaceSeat: deleteWorkspaceSeatFactory({ db: trx })
|
||||
})
|
||||
|
||||
return await onWorkspaceRoleDeleted(payload.acl)
|
||||
},
|
||||
{ db }
|
||||
)
|
||||
}),
|
||||
eventBus.listen(WorkspaceEvents.RoleUpdated, async ({ payload }) => {
|
||||
const trx = await db.transaction()
|
||||
const onWorkspaceRoleUpdated = onWorkspaceRoleUpdatedFactory({
|
||||
getWorkspaceWithPlan: getWorkspaceWithPlanFactory({ db }),
|
||||
getWorkspaceRoleToDefaultProjectRoleMapping:
|
||||
getWorkspaceRoleToDefaultProjectRoleMappingFactory({
|
||||
getWorkspaceWithPlan: getWorkspaceWithPlanFactory({ db })
|
||||
}),
|
||||
queryAllWorkspaceProjects: queryAllWorkspaceProjectsFactory({ getStreams }),
|
||||
setStreamCollaborator: setStreamCollaboratorFactory({
|
||||
getUser: getUserFactory({ db }),
|
||||
validateStreamAccess: validateStreamAccessFactory({ authorizeResolver }),
|
||||
emitEvent: eventBus.emit,
|
||||
grantStreamPermissions: grantStreamPermissionsFactory({ db: trx }),
|
||||
isStreamCollaborator: isStreamCollaboratorFactory({
|
||||
getStream: getStreamFactory({ db })
|
||||
}),
|
||||
revokeStreamPermissions: revokeStreamPermissionsFactory({ db: trx })
|
||||
}),
|
||||
getStreamsCollaboratorCounts: getStreamsCollaboratorCountsFactory({ db })
|
||||
})
|
||||
await withTransaction(onWorkspaceRoleUpdated(payload), trx)
|
||||
await withTransaction(
|
||||
async ({ db: trx }) => {
|
||||
const onWorkspaceRoleUpdated = onWorkspaceRoleUpdatedFactory({
|
||||
getWorkspaceWithPlan: getWorkspaceWithPlanFactory({ db }),
|
||||
getWorkspaceRoleToDefaultProjectRoleMapping:
|
||||
getWorkspaceRoleToDefaultProjectRoleMappingFactory({
|
||||
getWorkspaceWithPlan: getWorkspaceWithPlanFactory({ db })
|
||||
}),
|
||||
queryAllWorkspaceProjects: queryAllWorkspaceProjectsFactory({
|
||||
getStreams
|
||||
}),
|
||||
setStreamCollaborator: setStreamCollaboratorFactory({
|
||||
getUser: getUserFactory({ db }),
|
||||
validateStreamAccess: validateStreamAccessFactory({
|
||||
authorizeResolver
|
||||
}),
|
||||
emitEvent: eventBus.emit,
|
||||
grantStreamPermissions: grantStreamPermissionsFactory({
|
||||
db: trx
|
||||
}),
|
||||
isStreamCollaborator: isStreamCollaboratorFactory({
|
||||
getStream: getStreamFactory({ db })
|
||||
}),
|
||||
revokeStreamPermissions: revokeStreamPermissionsFactory({
|
||||
db: trx
|
||||
})
|
||||
}),
|
||||
getStreamsCollaboratorCounts: getStreamsCollaboratorCountsFactory({ db })
|
||||
})
|
||||
return await onWorkspaceRoleUpdated(payload)
|
||||
},
|
||||
{ db }
|
||||
)
|
||||
}),
|
||||
eventBus.listen(WorkspaceEvents.SeatUpdated, async (payload) => {
|
||||
const trx = await db.transaction()
|
||||
const onWorkspaceSeatUpdated = onWorkspaceSeatUpdatedFactory({
|
||||
setStreamCollaborator: setStreamCollaboratorFactory({
|
||||
getUser: getUserFactory({ db }),
|
||||
validateStreamAccess: validateStreamAccessFactory({ authorizeResolver }),
|
||||
emitEvent: eventBus.emit,
|
||||
grantStreamPermissions: grantStreamPermissionsFactory({ db: trx }),
|
||||
isStreamCollaborator: isStreamCollaboratorFactory({
|
||||
getStream: getStreamFactory({ db })
|
||||
}),
|
||||
revokeStreamPermissions: revokeStreamPermissionsFactory({ db: trx })
|
||||
}),
|
||||
queryAllWorkspaceProjects: queryAllWorkspaceProjectsFactory({ getStreams }),
|
||||
getWorkspaceWithPlan: getWorkspaceWithPlanFactory({ db }),
|
||||
getWorkspaceRoleForUser: getWorkspaceRoleForUserFactory({ db }),
|
||||
getWorkspaceSeatTypeToProjectRoleMapping:
|
||||
getWorkspaceSeatTypeToProjectRoleMappingFactory({
|
||||
getWorkspaceWithPlan: getWorkspaceWithPlanFactory({ db })
|
||||
await withTransaction(
|
||||
async ({ db: trx }) => {
|
||||
const onWorkspaceSeatUpdated = onWorkspaceSeatUpdatedFactory({
|
||||
setStreamCollaborator: setStreamCollaboratorFactory({
|
||||
getUser: getUserFactory({ db }),
|
||||
validateStreamAccess: validateStreamAccessFactory({
|
||||
authorizeResolver
|
||||
}),
|
||||
emitEvent: eventBus.emit,
|
||||
grantStreamPermissions: grantStreamPermissionsFactory({ db: trx }),
|
||||
isStreamCollaborator: isStreamCollaboratorFactory({
|
||||
getStream: getStreamFactory({ db })
|
||||
}),
|
||||
revokeStreamPermissions: revokeStreamPermissionsFactory({ db: trx })
|
||||
}),
|
||||
queryAllWorkspaceProjects: queryAllWorkspaceProjectsFactory({
|
||||
getStreams
|
||||
}),
|
||||
getWorkspaceWithPlan: getWorkspaceWithPlanFactory({ db }),
|
||||
getWorkspaceRoleForUser: getWorkspaceRoleForUserFactory({ db }),
|
||||
getWorkspaceSeatTypeToProjectRoleMapping:
|
||||
getWorkspaceSeatTypeToProjectRoleMappingFactory({
|
||||
getWorkspaceWithPlan: getWorkspaceWithPlanFactory({ db })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
await withTransaction(onWorkspaceSeatUpdated(payload), trx)
|
||||
return await onWorkspaceSeatUpdated(payload)
|
||||
},
|
||||
{ db }
|
||||
)
|
||||
}),
|
||||
eventBus.listen('**', emitWorkspaceGraphqlSubscriptions),
|
||||
eventBus.listen(
|
||||
|
||||
@@ -733,17 +733,19 @@ export = FF_WORKSPACES_MODULE_ENABLED
|
||||
if (!role) {
|
||||
// this is currently not working with the command factory
|
||||
// TODO: include the onWorkspaceRoleDeletedFactory listener service
|
||||
const trx = await db.transaction()
|
||||
const deleteWorkspaceRole = deleteWorkspaceRoleFactory({
|
||||
deleteWorkspaceRole: repoDeleteWorkspaceRoleFactory({ db: trx }),
|
||||
getWorkspaceRoles: getWorkspaceRolesFactory({ db: trx }),
|
||||
emitWorkspaceEvent: getEventBus().emit
|
||||
})
|
||||
await withOperationLogging(
|
||||
async () =>
|
||||
await withTransaction(
|
||||
deleteWorkspaceRole({ workspaceId, userId }),
|
||||
trx
|
||||
async ({ db: trx }) => {
|
||||
const deleteWorkspaceRole = deleteWorkspaceRoleFactory({
|
||||
deleteWorkspaceRole: repoDeleteWorkspaceRoleFactory({ db: trx }),
|
||||
getWorkspaceRoles: getWorkspaceRolesFactory({ db: trx }),
|
||||
emitWorkspaceEvent: getEventBus().emit
|
||||
})
|
||||
|
||||
return await deleteWorkspaceRole({ workspaceId, userId })
|
||||
},
|
||||
{ db }
|
||||
),
|
||||
{
|
||||
logger,
|
||||
@@ -758,18 +760,18 @@ export = FF_WORKSPACES_MODULE_ENABLED
|
||||
const updateWorkspaceRole = commandFactory({
|
||||
db,
|
||||
eventBus,
|
||||
operationFactory: ({ db, emit }) =>
|
||||
operationFactory: ({ trx, emit }) =>
|
||||
updateWorkspaceRoleFactory({
|
||||
upsertWorkspaceRole: upsertWorkspaceRoleFactory({ db }),
|
||||
getWorkspaceWithDomains: getWorkspaceWithDomainsFactory({ db }),
|
||||
upsertWorkspaceRole: upsertWorkspaceRoleFactory({ db: trx }),
|
||||
getWorkspaceWithDomains: getWorkspaceWithDomainsFactory({ db: trx }),
|
||||
findVerifiedEmailsByUserId: findVerifiedEmailsByUserIdFactory({
|
||||
db
|
||||
db: trx
|
||||
}),
|
||||
getWorkspaceRoles: getWorkspaceRolesFactory({ db }),
|
||||
getWorkspaceRoles: getWorkspaceRolesFactory({ db: trx }),
|
||||
emitWorkspaceEvent: emit,
|
||||
ensureValidWorkspaceRoleSeat: ensureValidWorkspaceRoleSeatFactory({
|
||||
createWorkspaceSeat: createWorkspaceSeatFactory({ db }),
|
||||
getWorkspaceUserSeat: getWorkspaceUserSeatFactory({ db }),
|
||||
createWorkspaceSeat: createWorkspaceSeatFactory({ db: trx }),
|
||||
getWorkspaceUserSeat: getWorkspaceUserSeatFactory({ db: trx }),
|
||||
eventEmit: emit
|
||||
})
|
||||
})
|
||||
@@ -946,17 +948,22 @@ export = FF_WORKSPACES_MODULE_ENABLED
|
||||
})
|
||||
// this is currently not working with the command factory
|
||||
// TODO: include the onWorkspaceRoleDeletedFactory listener service
|
||||
const trx = await db.transaction()
|
||||
const deleteWorkspaceRole = deleteWorkspaceRoleFactory({
|
||||
deleteWorkspaceRole: repoDeleteWorkspaceRoleFactory({ db: trx }),
|
||||
getWorkspaceRoles: getWorkspaceRolesFactory({ db: trx }),
|
||||
emitWorkspaceEvent: getEventBus().emit
|
||||
})
|
||||
await withOperationLogging(
|
||||
async () =>
|
||||
await withTransaction(
|
||||
deleteWorkspaceRole({ workspaceId, userId: context.userId! }),
|
||||
trx
|
||||
async ({ db: trx }) => {
|
||||
const deleteWorkspaceRole = deleteWorkspaceRoleFactory({
|
||||
deleteWorkspaceRole: repoDeleteWorkspaceRoleFactory({ db: trx }),
|
||||
getWorkspaceRoles: getWorkspaceRolesFactory({ db: trx }),
|
||||
emitWorkspaceEvent: getEventBus().emit
|
||||
})
|
||||
|
||||
return await deleteWorkspaceRole({
|
||||
workspaceId,
|
||||
userId: context.userId!
|
||||
})
|
||||
},
|
||||
{ db }
|
||||
),
|
||||
{
|
||||
logger,
|
||||
|
||||
@@ -257,87 +257,99 @@ export const getSsoRouter = (): Router => {
|
||||
query: oidcCallbackRequestQuery
|
||||
}),
|
||||
async (req, res, next) => {
|
||||
const trx = await db.transaction()
|
||||
const handleOidcCallback = handleOidcCallbackFactory({
|
||||
getWorkspaceRoles: getWorkspaceRolesFactory({ db: trx }),
|
||||
getWorkspaceBySlug: getWorkspaceBySlugFactory({ db: trx }),
|
||||
createOidcProvider: createOidcProviderFactory({
|
||||
getOIDCProviderValidationRequest: getOIDCProviderValidationRequestFactory({
|
||||
redis: getGenericRedis(),
|
||||
decrypt: getDecryptor()
|
||||
}),
|
||||
saveSsoProviderRegistration: saveSsoProviderRegistrationFactory({
|
||||
getWorkspaceSsoProvider: getWorkspaceSsoProviderFactory({
|
||||
db: trx,
|
||||
decrypt: getDecryptor()
|
||||
}),
|
||||
storeProviderRecord: storeSsoProviderRecordFactory({
|
||||
db: trx,
|
||||
encrypt: getEncryptor()
|
||||
}),
|
||||
associateSsoProviderWithWorkspace: associateSsoProviderWithWorkspaceFactory(
|
||||
{
|
||||
db: trx
|
||||
}
|
||||
)
|
||||
})
|
||||
}),
|
||||
getOidcProvider: getOidcProviderFactory({
|
||||
getWorkspaceSsoProvider: getWorkspaceSsoProviderFactory({
|
||||
db: trx,
|
||||
decrypt: getDecryptor()
|
||||
})
|
||||
}),
|
||||
getOidcProviderUserData: getOidcProviderUserDataFactory(),
|
||||
tryGetSpeckleUserData: tryGetSpeckleUserDataFactory({
|
||||
findEmail: findEmailFactory({ db: trx }),
|
||||
getUser: getUserFactory({ db: trx }),
|
||||
getUserEmails: findEmailsByUserIdFactory({ db: trx })
|
||||
}),
|
||||
createWorkspaceUserFromSsoProfile: createWorkspaceUserFromSsoProfileFactory({
|
||||
createUser: createUserFactory({
|
||||
getServerInfo: getServerInfoFactory({ db: trx }),
|
||||
findEmail: findEmailFactory({ db: trx }),
|
||||
storeUser: storeUserFactory({ db: trx }),
|
||||
countAdminUsers: countAdminUsersFactory({ db: trx }),
|
||||
storeUserAcl: storeUserAclFactory({ db: trx }),
|
||||
validateAndCreateUserEmail: validateAndCreateUserEmailFactory({
|
||||
createUserEmail: createUserEmailFactory({ db: trx }),
|
||||
ensureNoPrimaryEmailForUser: ensureNoPrimaryEmailForUserFactory({
|
||||
db: trx
|
||||
try {
|
||||
await withTransaction(
|
||||
async ({ db: trx }) => {
|
||||
const handleOidcCallback = handleOidcCallbackFactory({
|
||||
getWorkspaceRoles: getWorkspaceRolesFactory({ db: trx }),
|
||||
getWorkspaceBySlug: getWorkspaceBySlugFactory({ db: trx }),
|
||||
createOidcProvider: createOidcProviderFactory({
|
||||
getOIDCProviderValidationRequest:
|
||||
getOIDCProviderValidationRequestFactory({
|
||||
redis: getGenericRedis(),
|
||||
decrypt: getDecryptor()
|
||||
}),
|
||||
saveSsoProviderRegistration: saveSsoProviderRegistrationFactory({
|
||||
getWorkspaceSsoProvider: getWorkspaceSsoProviderFactory({
|
||||
db: trx,
|
||||
decrypt: getDecryptor()
|
||||
}),
|
||||
storeProviderRecord: storeSsoProviderRecordFactory({
|
||||
db: trx,
|
||||
encrypt: getEncryptor()
|
||||
}),
|
||||
associateSsoProviderWithWorkspace:
|
||||
associateSsoProviderWithWorkspaceFactory({
|
||||
db: trx
|
||||
})
|
||||
})
|
||||
}),
|
||||
findEmail: findEmailFactory({ db: trx }),
|
||||
updateEmailInvites: finalizeInvitedServerRegistrationFactory({
|
||||
deleteServerOnlyInvites: deleteServerOnlyInvitesFactory({ db: trx }),
|
||||
updateAllInviteTargets: updateAllInviteTargetsFactory({ db: trx })
|
||||
getOidcProvider: getOidcProviderFactory({
|
||||
getWorkspaceSsoProvider: getWorkspaceSsoProviderFactory({
|
||||
db: trx,
|
||||
decrypt: getDecryptor()
|
||||
})
|
||||
}),
|
||||
requestNewEmailVerification: requestNewEmailVerificationFactory({
|
||||
getOidcProviderUserData: getOidcProviderUserDataFactory(),
|
||||
tryGetSpeckleUserData: tryGetSpeckleUserDataFactory({
|
||||
findEmail: findEmailFactory({ db: trx }),
|
||||
getUser: getUserFactory({ db: trx }),
|
||||
getServerInfo: getServerInfoFactory({ db: trx }),
|
||||
deleteOldAndInsertNewVerification:
|
||||
deleteOldAndInsertNewVerificationFactory({ db: trx }),
|
||||
renderEmail,
|
||||
sendEmail
|
||||
})
|
||||
}),
|
||||
emitEvent: getEventBus().emit
|
||||
}),
|
||||
upsertWorkspaceRole: upsertWorkspaceRoleFactory({ db: trx }),
|
||||
findInvite: findInviteFactory({ db: trx }),
|
||||
deleteInvite: deleteInviteFactory({ db: trx })
|
||||
}),
|
||||
linkUserWithSsoProvider: linkUserWithSsoProviderFactory({
|
||||
findEmailsByUserId: findEmailsByUserIdFactory({ db: trx }),
|
||||
createUserEmail: createUserEmailFactory({ db: trx }),
|
||||
updateUserEmail: updateUserEmailFactory({ db: trx }),
|
||||
logger: req.log
|
||||
}),
|
||||
upsertUserSsoSession: upsertUserSsoSessionFactory({ db: trx })
|
||||
})
|
||||
getUserEmails: findEmailsByUserIdFactory({ db: trx })
|
||||
}),
|
||||
createWorkspaceUserFromSsoProfile:
|
||||
createWorkspaceUserFromSsoProfileFactory({
|
||||
createUser: createUserFactory({
|
||||
getServerInfo: getServerInfoFactory({ db: trx }),
|
||||
findEmail: findEmailFactory({ db: trx }),
|
||||
storeUser: storeUserFactory({ db: trx }),
|
||||
countAdminUsers: countAdminUsersFactory({ db: trx }),
|
||||
storeUserAcl: storeUserAclFactory({ db: trx }),
|
||||
validateAndCreateUserEmail: validateAndCreateUserEmailFactory({
|
||||
createUserEmail: createUserEmailFactory({ db: trx }),
|
||||
ensureNoPrimaryEmailForUser: ensureNoPrimaryEmailForUserFactory({
|
||||
db: trx
|
||||
}),
|
||||
findEmail: findEmailFactory({ db: trx }),
|
||||
updateEmailInvites: finalizeInvitedServerRegistrationFactory({
|
||||
deleteServerOnlyInvites: deleteServerOnlyInvitesFactory({
|
||||
db: trx
|
||||
}),
|
||||
updateAllInviteTargets: updateAllInviteTargetsFactory({
|
||||
db: trx
|
||||
})
|
||||
}),
|
||||
requestNewEmailVerification: requestNewEmailVerificationFactory({
|
||||
findEmail: findEmailFactory({ db: trx }),
|
||||
getUser: getUserFactory({ db: trx }),
|
||||
getServerInfo: getServerInfoFactory({ db: trx }),
|
||||
deleteOldAndInsertNewVerification:
|
||||
deleteOldAndInsertNewVerificationFactory({
|
||||
db: trx
|
||||
}),
|
||||
renderEmail,
|
||||
sendEmail
|
||||
})
|
||||
}),
|
||||
emitEvent: getEventBus().emit
|
||||
}),
|
||||
upsertWorkspaceRole: upsertWorkspaceRoleFactory({ db: trx }),
|
||||
findInvite: findInviteFactory({ db: trx }),
|
||||
deleteInvite: deleteInviteFactory({ db: trx })
|
||||
}),
|
||||
linkUserWithSsoProvider: linkUserWithSsoProviderFactory({
|
||||
findEmailsByUserId: findEmailsByUserIdFactory({ db: trx }),
|
||||
createUserEmail: createUserEmailFactory({ db: trx }),
|
||||
updateUserEmail: updateUserEmailFactory({ db: trx }),
|
||||
logger: req.log
|
||||
}),
|
||||
upsertUserSsoSession: upsertUserSsoSessionFactory({ db: trx })
|
||||
})
|
||||
|
||||
await handleOidcCallback(req, res, next)
|
||||
},
|
||||
{ db }
|
||||
)
|
||||
|
||||
try {
|
||||
await withTransaction(handleOidcCallback(req, res, next), trx)
|
||||
return next()
|
||||
} catch (e) {
|
||||
const errorMessage = getErrorMessage(e)
|
||||
|
||||
Reference in New Issue
Block a user