From aa4f31927712cbeaf993a6c31bac1bc1cdebd581 Mon Sep 17 00:00:00 2001 From: Kristaps Fabians Geikins Date: Wed, 9 Oct 2024 09:10:20 +0100 Subject: [PATCH] chore(server): IoC 32 - createStreamFactory (#3204) --- .../tests/activitySummary.spec.ts | 55 +++++- .../server/modules/auth/tests/auth.spec.js | 66 ++++++- .../tests/blobstorage.graph.spec.js | 67 ++++++- .../tests/blobstorage.integration.spec.js | 67 ++++++- .../modules/cli/commands/download/project.ts | 46 ++++- .../comments/tests/comments.graph.spec.js | 70 +++++++- .../modules/comments/tests/comments.spec.js | 66 ++++++- .../modules/core/domain/streams/operations.ts | 32 +++- .../modules/core/events/projectsEmitter.ts | 2 + .../modules/core/graph/resolvers/projects.ts | 47 ++++- .../modules/core/graph/resolvers/streams.ts | 52 +++++- .../modules/core/repositories/streams.ts | 113 ++++++------ .../server/modules/core/services/streams.js | 15 -- .../modules/core/services/streams/clone.ts | 3 +- .../core/services/streams/management.ts | 169 +++++++++--------- .../core/services/streams/onboarding.ts | 50 +++++- .../modules/core/tests/branches.spec.js | 63 ++++++- .../server/modules/core/tests/commits.spec.js | 63 ++++++- .../core/tests/favoriteStreams.spec.js | 67 ++++++- .../server/modules/core/tests/generic.spec.js | 67 ++++++- .../server/modules/core/tests/objects.spec.js | 67 ++++++- .../server/modules/core/tests/rest.spec.js | 67 ++++++- .../server/modules/core/tests/streams.spec.ts | 51 +++++- .../server/modules/core/tests/users.spec.js | 64 ++++++- .../modules/core/tests/usersAdminList.spec.ts | 56 +++++- .../server/modules/cross-server-sync/index.ts | 45 ++++- .../cross-server-sync/services/project.ts | 4 +- .../tests/fileuploads.integration.spec.ts | 57 +++++- .../server/modules/stats/tests/stats.spec.ts | 58 +++++- .../modules/webhooks/tests/cleanup.spec.ts | 58 +++++- .../modules/webhooks/tests/webhooks.spec.js | 67 ++++++- packages/server/scripts/streamObjects.js | 67 ++++++- .../test/speckle-helpers/streamHelper.ts | 57 +++++- 33 files changed, 1696 insertions(+), 202 deletions(-) diff --git a/packages/server/modules/activitystream/tests/activitySummary.spec.ts b/packages/server/modules/activitystream/tests/activitySummary.spec.ts index 34b6ebb72..95f820d29 100644 --- a/packages/server/modules/activitystream/tests/activitySummary.spec.ts +++ b/packages/server/modules/activitystream/tests/activitySummary.spec.ts @@ -6,7 +6,7 @@ import { sendActivityNotificationsFactory } from '@/modules/activitystream/services/summary' import { expect } from 'chai' -import { createStream, deleteStream } from '@/modules/core/services/streams' +import { deleteStream } from '@/modules/core/services/streams' import { ActionTypes, ResourceTypes } from '@/modules/activitystream/helpers/types' import { ActivityDigestMessage, @@ -19,7 +19,28 @@ import { saveActivityFactory } from '@/modules/activitystream/repositories' import { db } from '@/db/knex' -import { getStreamFactory } from '@/modules/core/repositories/streams' +import { + createStreamFactory, + getStreamFactory +} from '@/modules/core/repositories/streams' +import { + createStreamReturnRecordFactory, + legacyCreateStreamFactory +} from '@/modules/core/services/streams/management' +import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} from '@/modules/serverinvites/repositories/serverInvites' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { getEventBus } from '@/modules/shared/services/eventBus' +import { getUsers } from '@/modules/core/repositories/users' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' +import { createBranchFactory } from '@/modules/core/repositories/branches' +import { publish } from '@/modules/shared/utils/subscriptions' const cleanup = async () => { await truncateTables([StreamActivity.name, Users.name]) @@ -31,6 +52,36 @@ const createActivitySummary = createActivitySummaryFactory({ getStream, getActivity: getActivityFactory({ db }) }) +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) describe('Activity summary @activity', () => { const userA: BasicTestUser = { diff --git a/packages/server/modules/auth/tests/auth.spec.js b/packages/server/modules/auth/tests/auth.spec.js index ab6c8a0b7..5efae8808 100644 --- a/packages/server/modules/auth/tests/auth.spec.js +++ b/packages/server/modules/auth/tests/auth.spec.js @@ -2,7 +2,6 @@ const crs = require('crypto-random-string') const chai = require('chai') const request = require('supertest') const { createUser } = require('@/modules/core/services/users') -const { createStream } = require('@/modules/core/services/streams') const { updateServerInfo } = require('@/modules/core/services/generic') const { getUserByEmail } = require('@/modules/core/services/users') @@ -12,12 +11,75 @@ const { beforeEachContext, initializeTestServer } = require('@/test/hooks') const { createStreamInviteDirectly } = require('@/test/speckle-helpers/inviteHelper') const { RateLimiterMemory } = require('rate-limiter-flexible') const { - findInviteFactory + findInviteFactory, + findUserByTargetFactory, + insertInviteAndDeleteOldFactory } = require('@/modules/serverinvites/repositories/serverInvites') const db = require('@/db/knex') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + getStreamFactory, + createStreamFactory +} = require('@/modules/core/repositories/streams') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { createBranchFactory } = require('@/modules/core/repositories/branches') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) const createInviteDirectly = createStreamInviteDirectly const findInvite = findInviteFactory({ db }) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) + const expect = chai.expect let app diff --git a/packages/server/modules/blobstorage/tests/blobstorage.graph.spec.js b/packages/server/modules/blobstorage/tests/blobstorage.graph.spec.js index 920e24def..68f82035b 100644 --- a/packages/server/modules/blobstorage/tests/blobstorage.graph.spec.js +++ b/packages/server/modules/blobstorage/tests/blobstorage.graph.spec.js @@ -1,12 +1,77 @@ const { buildApolloServer } = require('@/app') const { truncateTables } = require('@/test/hooks') -const { createStream } = require('@/modules/core/services/streams') const { createUser } = require('@/modules/core/services/users') const { gql } = require('graphql-tag') const { createBlobs } = require('@/modules/blobstorage/tests/helpers') const { expect } = require('chai') const { Users, Streams } = require('@/modules/core/dbSchema') const { createAuthedTestContext, executeOperation } = require('@/test/graphqlHelper') +const { + getStreamFactory, + createStreamFactory +} = require('@/modules/core/repositories/streams') +const { db } = require('@/db/knex') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { createBranchFactory } = require('@/modules/core/repositories/branches') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') + +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) describe('Blobs graphql @blobstorage', () => { /** @type {import('@/test/graphqlHelper').ServerAndContext} */ diff --git a/packages/server/modules/blobstorage/tests/blobstorage.integration.spec.js b/packages/server/modules/blobstorage/tests/blobstorage.integration.spec.js index f12bf600a..a33f7e6bc 100644 --- a/packages/server/modules/blobstorage/tests/blobstorage.integration.spec.js +++ b/packages/server/modules/blobstorage/tests/blobstorage.integration.spec.js @@ -2,10 +2,75 @@ const { Buffer } = require('node:buffer') const request = require('supertest') const expect = require('chai').expect const { beforeEachContext } = require('@/test/hooks') -const { createStream } = require('@/modules/core/services/streams') const { createToken } = require('@/modules/core/services/tokens') const { createUser } = require('@/modules/core/services/users') const { Scopes } = require('@/modules/core/helpers/mainConstants') +const { + getStreamFactory, + createStreamFactory +} = require('@/modules/core/repositories/streams') +const { db } = require('@/db/knex') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { createBranchFactory } = require('@/modules/core/repositories/branches') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') + +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) describe('Blobs integration @blobstorage', () => { let app diff --git a/packages/server/modules/cli/commands/download/project.ts b/packages/server/modules/cli/commands/download/project.ts index 53edb4505..354ffb422 100644 --- a/packages/server/modules/cli/commands/download/project.ts +++ b/packages/server/modules/cli/commands/download/project.ts @@ -3,6 +3,7 @@ import { cliLogger } from '@/logging/logging' import { downloadProjectFactory } from '@/modules/cross-server-sync/services/project' import { downloadCommitFactory } from '@/modules/cross-server-sync/services/commit' import { + createStreamFactory, getStreamCollaboratorsFactory, getStreamFactory, markCommitStreamUpdated @@ -15,7 +16,7 @@ import { getStreamBranchesByNameFactory, markCommitBranchUpdatedFactory } from '@/modules/core/repositories/branches' -import { getUser } from '@/modules/core/repositories/users' +import { getUser, getUsers } from '@/modules/core/repositories/users' import { createCommitByBranchIdFactory } from '@/modules/core/services/commit/management' import { createObject } from '@/modules/core/services/objects' import { @@ -26,7 +27,6 @@ import { createCommentReplyAndNotifyFactory, createCommentThreadAndNotifyFactory } from '@/modules/comments/services/management' -import { createStreamReturnRecord } from '@/modules/core/services/streams/management' import { createBranchAndNotifyFactory } from '@/modules/core/services/branch/management' import { CommentsEmitter } from '@/modules/comments/events/emitter' import { @@ -57,6 +57,20 @@ import { validateInputAttachmentsFactory } from '@/modules/comments/services/com import { addBranchCreatedActivity } from '@/modules/activitystream/services/branchActivity' import { VersionsEmitter } from '@/modules/core/events/versionsEmitter' import { addCommitCreatedActivity } from '@/modules/activitystream/services/commitActivity' +import { createStreamReturnRecordFactory } from '@/modules/core/services/streams/management' +import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} from '@/modules/serverinvites/repositories/serverInvites' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { getEventBus } from '@/modules/shared/services/eventBus' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' +import { saveActivityFactory } from '@/modules/activitystream/repositories' +import { publish } from '@/modules/shared/utils/subscriptions' const command: CommandModule< unknown, @@ -140,6 +154,34 @@ const command: CommandModule< addCommitCreatedActivity }) + const createStreamReturnRecord = createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity: addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish + }), + projectsEventsEmitter: ProjectsEmitter.emit + }) + const getStreamCollaborators = getStreamCollaboratorsFactory({ db }) const getStreamBranchByName = getStreamBranchByNameFactory({ db }) const downloadProject = downloadProjectFactory({ diff --git a/packages/server/modules/comments/tests/comments.graph.spec.js b/packages/server/modules/comments/tests/comments.graph.spec.js index 58aa2d277..cd175eb0a 100644 --- a/packages/server/modules/comments/tests/comments.graph.spec.js +++ b/packages/server/modules/comments/tests/comments.graph.spec.js @@ -10,7 +10,6 @@ const { } = require('@/modules/core/services/streams') const { createUser } = require('@/modules/core/services/users') const { gql } = require('graphql-tag') -const { createStream } = require('@/modules/core/services/streams') const { createObject } = require('@/modules/core/services/objects') const { convertBasicStringToDocument @@ -49,14 +48,47 @@ const { const { getBranchByIdFactory, markCommitBranchUpdatedFactory, - getStreamBranchByNameFactory + getStreamBranchByNameFactory, + createBranchFactory } = require('@/modules/core/repositories/branches') -const { markCommitStreamUpdated } = require('@/modules/core/repositories/streams') +const { + markCommitStreamUpdated, + getStreamFactory, + createStreamFactory +} = require('@/modules/core/repositories/streams') const { VersionsEmitter } = require('@/modules/core/events/versionsEmitter') const { addCommitCreatedActivity } = require('@/modules/activitystream/services/commitActivity') const { getObjectFactory } = require('@/modules/core/repositories/objects') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') const streamResourceCheck = streamResourceCheckFactory({ checkStreamResourceAccess: checkStreamResourceAccessFactory({ db }) @@ -93,6 +125,38 @@ const createCommitByBranchName = createCommitByBranchNameFactory({ getBranchById: getBranchByIdFactory({ db }) }) +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) + function buildCommentInputFromString(textString) { return convertBasicStringToDocument(textString) } diff --git a/packages/server/modules/comments/tests/comments.spec.js b/packages/server/modules/comments/tests/comments.spec.js index 9fc91e1c9..d76239744 100644 --- a/packages/server/modules/comments/tests/comments.spec.js +++ b/packages/server/modules/comments/tests/comments.spec.js @@ -4,7 +4,6 @@ const expect = require('chai').expect const crs = require('crypto-random-string') const { beforeEachContext, truncateTables } = require('@/test/hooks') const { createUser } = require('@/modules/core/services/users') -const { createStream } = require('@/modules/core/services/streams') const { createObject } = require('@/modules/core/services/objects') const { @@ -57,7 +56,8 @@ const { getBlobsFactory } = require('@/modules/blobstorage/repositories') const { CommentsEmitter } = require('@/modules/comments/events/emitter') const { markCommitStreamUpdated, - getStreamFactory + getStreamFactory, + createStreamFactory } = require('@/modules/core/repositories/streams') const { createCommitByBranchIdFactory, @@ -71,13 +71,42 @@ const { const { getBranchByIdFactory, markCommitBranchUpdatedFactory, - getStreamBranchByNameFactory + getStreamBranchByNameFactory, + createBranchFactory } = require('@/modules/core/repositories/branches') const { VersionsEmitter } = require('@/modules/core/events/versionsEmitter') const { addCommitCreatedActivity } = require('@/modules/activitystream/services/commitActivity') const { getObjectFactory } = require('@/modules/core/repositories/objects') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') const getStream = getStreamFactory({ db }) const streamResourceCheck = streamResourceCheckFactory({ @@ -144,6 +173,37 @@ const createCommitByBranchName = createCommitByBranchNameFactory({ getBranchById: getBranchByIdFactory({ db }) }) +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) + function buildCommentInputFromString(textString) { return convertBasicStringToDocument(textString) } diff --git a/packages/server/modules/core/domain/streams/operations.ts b/packages/server/modules/core/domain/streams/operations.ts index 6fd50654a..2238a857c 100644 --- a/packages/server/modules/core/domain/streams/operations.ts +++ b/packages/server/modules/core/domain/streams/operations.ts @@ -1,9 +1,15 @@ import { StreamWithCommitId, StreamWithOptionalRole, - LimitedUserWithStreamRole + LimitedUserWithStreamRole, + Stream } from '@/modules/core/domain/streams/types' -import { Optional, StreamRoles } from '@speckle/shared' +import { TokenResourceIdentifier } from '@/modules/core/domain/tokens/types' +import { + ProjectCreateInput, + StreamCreateInput +} from '@/modules/core/graph/generated/graphql' +import { MaybeNullOrUndefined, Optional, StreamRoles } from '@speckle/shared' import { Knex } from 'knex' export type GetStreams = ( @@ -38,3 +44,25 @@ export type GetStreamCollaborators = ( streamId: string, type?: StreamRoles ) => Promise> + +export type StoreStream = ( + input: StreamCreateInput | ProjectCreateInput, + options?: Partial<{ + ownerId: string + trx: Knex.Transaction + }> +) => Promise + +export type CreateStream = ( + params: (StreamCreateInput | ProjectCreateInput) & { + ownerId: string + ownerResourceAccessRules?: MaybeNullOrUndefined + }, + options?: Partial<{ + createActivity: boolean + }> +) => Promise + +export type LegacyCreateStream = ( + params: StreamCreateInput & { ownerId: string } +) => Promise diff --git a/packages/server/modules/core/events/projectsEmitter.ts b/packages/server/modules/core/events/projectsEmitter.ts index 89ecbfc86..01e21cf2e 100644 --- a/packages/server/modules/core/events/projectsEmitter.ts +++ b/packages/server/modules/core/events/projectsEmitter.ts @@ -17,3 +17,5 @@ const { emit, listen } = initializeModuleEventEmitter({ }) export const ProjectsEmitter = { emit, listen, events: ProjectEvents } +export type ProjectsEventsEmitter = (typeof ProjectsEmitter)['emit'] +export type ProjectsEventsListener = (typeof ProjectsEmitter)['listen'] diff --git a/packages/server/modules/core/graph/resolvers/projects.ts b/packages/server/modules/core/graph/resolvers/projects.ts index 0ff1b19d9..e026dd961 100644 --- a/packages/server/modules/core/graph/resolvers/projects.ts +++ b/packages/server/modules/core/graph/resolvers/projects.ts @@ -1,7 +1,10 @@ import { db } from '@/db/knex' +import { saveActivityFactory } from '@/modules/activitystream/repositories' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' import { RateLimitError } from '@/modules/core/errors/ratelimit' import { StreamNotFoundError } from '@/modules/core/errors/stream' import { WorkspacesModuleDisabledError } from '@/modules/core/errors/workspaces' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' import { ProjectVisibility, Resolvers, @@ -10,35 +13,75 @@ import { import { isWorkspacesModuleEnabled } from '@/modules/core/helpers/features' import { Roles, Scopes, StreamRoles } from '@/modules/core/helpers/mainConstants' import { isResourceAllowed, toProjectIdWhitelist } from '@/modules/core/helpers/token' +import { createBranchFactory } from '@/modules/core/repositories/branches' import { getUserStreamsCount, getUserStreams, getStreamFactory, - getStreamCollaboratorsFactory + getStreamCollaboratorsFactory, + createStreamFactory } from '@/modules/core/repositories/streams' +import { getUsers } from '@/modules/core/repositories/users' import { getRateLimitResult, isRateLimitBreached } from '@/modules/core/services/ratelimiter' import { - createStreamReturnRecord, + createStreamReturnRecordFactory, deleteStreamAndNotify, updateStreamAndNotify, updateStreamRoleAndNotify } from '@/modules/core/services/streams/management' import { createOnboardingStream } from '@/modules/core/services/streams/onboarding' import { removeStreamCollaborator } from '@/modules/core/services/streams/streamAccessService' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} from '@/modules/serverinvites/repositories/serverInvites' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' import { authorizeResolver, validateScopes } from '@/modules/shared' import { throwForNotHavingServerRole } from '@/modules/shared/authz' +import { getEventBus } from '@/modules/shared/services/eventBus' import { filteredSubscribe, ProjectSubscriptions, + publish, UserSubscriptions } from '@/modules/shared/utils/subscriptions' import { has } from 'lodash' const getStream = getStreamFactory({ db }) const getStreamCollaborators = getStreamCollaboratorsFactory({ db }) +const createStreamReturnRecord = createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity: addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish + }), + projectsEventsEmitter: ProjectsEmitter.emit +}) export = { Query: { diff --git a/packages/server/modules/core/graph/resolvers/streams.ts b/packages/server/modules/core/graph/resolvers/streams.ts index e371993fa..1c14b2047 100644 --- a/packages/server/modules/core/graph/resolvers/streams.ts +++ b/packages/server/modules/core/graph/resolvers/streams.ts @@ -9,6 +9,7 @@ import { } from '@/modules/core/services/streams' import { filteredSubscribe, + publish, StreamSubscriptions } from '@/modules/shared/utils/subscriptions' import { authorizeResolver, validateScopes } from '@/modules/shared' @@ -16,7 +17,10 @@ import { getRateLimitResult, isRateLimitBreached } from '@/modules/core/services/ratelimiter' -import { getPendingProjectCollaboratorsFactory } from '@/modules/serverinvites/services/projectInviteManagement' +import { + getPendingProjectCollaboratorsFactory, + inviteUsersToProjectFactory +} from '@/modules/serverinvites/services/projectInviteManagement' import { removePrivateFields } from '@/modules/core/helpers/userHelper' import { removeStreamCollaborator } from '@/modules/core/services/streams/streamAccessService' import { getDiscoverableStreams } from '@/modules/core/services/streams/discoverableStreams' @@ -24,12 +28,13 @@ import { get } from 'lodash' import { getUserStreamsCount, getUserStreams, - getStreamFactory + getStreamFactory, + createStreamFactory } from '@/modules/core/repositories/streams' import { + createStreamReturnRecordFactory, deleteStreamAndNotify, updateStreamAndNotify, - createStreamReturnRecord, updateStreamRoleAndNotify } from '@/modules/core/services/streams/management' import { adminOverrideEnabled } from '@/modules/shared/helpers/envHelper' @@ -44,13 +49,52 @@ import { TokenResourceIdentifierType, UserStreamsArgs } from '@/modules/core/graph/generated/graphql' -import { queryAllResourceInvitesFactory } from '@/modules/serverinvites/repositories/serverInvites' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory, + queryAllResourceInvitesFactory +} from '@/modules/serverinvites/repositories/serverInvites' import db from '@/db/knex' import { getInvitationTargetUsersFactory } from '@/modules/serverinvites/services/retrieval' import { getUsers } from '@/modules/core/repositories/users' import { BadRequestError } from '@/modules/shared/errors' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { getEventBus } from '@/modules/shared/services/eventBus' +import { createBranchFactory } from '@/modules/core/repositories/branches' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' +import { saveActivityFactory } from '@/modules/activitystream/repositories' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' const getStream = getStreamFactory({ db }) +const createStreamReturnRecord = createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity: addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish + }), + projectsEventsEmitter: ProjectsEmitter.emit +}) const getUserStreamsCore = async ( forOtherUser: boolean, diff --git a/packages/server/modules/core/repositories/streams.ts b/packages/server/modules/core/repositories/streams.ts index a123f8ee4..864415b5c 100644 --- a/packages/server/modules/core/repositories/streams.ts +++ b/packages/server/modules/core/repositories/streams.ts @@ -72,6 +72,7 @@ import { StreamWithOptionalRole } from '@/modules/core/domain/streams/types' import { + StoreStream, GetCommitStream, GetCommitStreams, GetStream, @@ -815,63 +816,67 @@ export async function getUserStreamsCount(params: UserStreamsQueryCountParams) { return parseInt(res.count) } -export async function createStream( - input: StreamCreateInput | ProjectCreateInput, - options?: Partial<{ - /** - * If set, will assign owner permissions to this user - */ - ownerId: string - trx: Knex.Transaction - }> -) { - const { name, description } = input - const { ownerId, trx } = options || {} +export const createStreamFactory = + (deps: { db: Knex }): StoreStream => + async ( + input: StreamCreateInput | ProjectCreateInput, + options?: Partial<{ + /** + * If set, will assign owner permissions to this user + */ + ownerId: string + trx: Knex.Transaction + }> + ) => { + const { name, description } = input + const { ownerId, trx } = options || {} - let shouldBePublic: boolean, shouldBeDiscoverable: boolean - if (isProjectCreateInput(input)) { - shouldBeDiscoverable = input.visibility === ProjectVisibility.Public - shouldBePublic = - !input.visibility || - [ProjectVisibility.Public, ProjectVisibility.Unlisted].includes(input.visibility) - } else { - shouldBePublic = input.isPublic !== false - shouldBeDiscoverable = input.isDiscoverable !== false && shouldBePublic + let shouldBePublic: boolean, shouldBeDiscoverable: boolean + if (isProjectCreateInput(input)) { + shouldBeDiscoverable = input.visibility === ProjectVisibility.Public + shouldBePublic = + !input.visibility || + [ProjectVisibility.Public, ProjectVisibility.Unlisted].includes( + input.visibility + ) + } else { + shouldBePublic = input.isPublic !== false + shouldBeDiscoverable = input.isDiscoverable !== false && shouldBePublic + } + + const workspaceId = 'workspaceId' in input ? input.workspaceId : null + + const id = generateId() + const stream = { + id, + name: name || generateStreamName(), + description: description || '', + isPublic: shouldBePublic, + isDiscoverable: shouldBeDiscoverable, + updatedAt: knex.fn.now(), + workspaceId: workspaceId || null + } + + // Create the stream & set up permissions + const streamQuery = tables.streams(deps.db).insert(stream, '*') + if (trx) streamQuery.transacting(trx) + + const insertResults = await streamQuery + const newStream = insertResults[0] as StreamRecord + + if (ownerId) { + const streamAclQuery = tables.streamAcl(deps.db).insert({ + userId: ownerId, + resourceId: id, + role: Roles.Stream.Owner + }) + if (trx) streamAclQuery.transacting(trx) + await streamAclQuery + } + + return newStream } - const workspaceId = 'workspaceId' in input ? input.workspaceId : null - - const id = generateId() - const stream = { - id, - name: name || generateStreamName(), - description: description || '', - isPublic: shouldBePublic, - isDiscoverable: shouldBeDiscoverable, - updatedAt: knex.fn.now(), - workspaceId: workspaceId || null - } - - // Create the stream & set up permissions - const streamQuery = Streams.knex().insert(stream, '*') - if (trx) streamQuery.transacting(trx) - - const insertResults = await streamQuery - const newStream = insertResults[0] as StreamRecord - - if (ownerId) { - const streamAclQuery = StreamAcl.knex().insert({ - userId: ownerId, - resourceId: id, - role: Roles.Stream.Owner - }) - if (trx) streamAclQuery.transacting(trx) - await streamAclQuery - } - - return newStream -} - export async function getUserStreamCounts(params: { userIds: string[] /** diff --git a/packages/server/modules/core/services/streams.js b/packages/server/modules/core/services/streams.js index 3e9a98681..bd0b145ef 100644 --- a/packages/server/modules/core/services/streams.js +++ b/packages/server/modules/core/services/streams.js @@ -14,9 +14,6 @@ const { } = require('@/modules/core/repositories/streams') const { UnauthorizedError, InvalidArgumentError } = require('@/modules/shared/errors') const { dbLogger } = require('@/logging/logging') -const { - createStreamReturnRecord -} = require('@/modules/core/services/streams/management') const { isResourceAllowed } = require('@/modules/core/helpers/token') const { TokenResourceIdentifierType @@ -30,18 +27,6 @@ const { */ module.exports = { - /** - * @deprecated Use createStreamReturnRecord() - * @param {import('@/modules/core/graph/generated/graphql').StreamCreateInput & {ownerId: string}} param0 - * @returns {Promise} - */ - async createStream(params) { - const { id } = await createStreamReturnRecord(params, { - createActivity: false - }) - return id - }, - /** * @deprecated Use updateStreamAndNotify or use the repository function directly * @param {import('@/modules/core/graph/generated/graphql').StreamUpdateInput} update diff --git a/packages/server/modules/core/services/streams/clone.ts b/packages/server/modules/core/services/streams/clone.ts index a5ca3a4cc..4176acc68 100644 --- a/packages/server/modules/core/services/streams/clone.ts +++ b/packages/server/modules/core/services/streams/clone.ts @@ -5,7 +5,7 @@ import { UserRecord } from '@/modules/core/helpers/types' import { - createStream, + createStreamFactory, getStreamFactory, StreamWithOptionalRole } from '@/modules/core/repositories/streams' @@ -103,6 +103,7 @@ const prepareState = async ( async function cloneStreamEntity(state: CloneStreamInitialState) { const { targetStream, user, trx } = state + const createStream = createStreamFactory({ db }) const newStream = await createStream( { name: targetStream.name, diff --git a/packages/server/modules/core/services/streams/management.ts b/packages/server/modules/core/services/streams/management.ts index f8889b0dd..7448ff6b7 100644 --- a/packages/server/modules/core/services/streams/management.ts +++ b/packages/server/modules/core/services/streams/management.ts @@ -15,12 +15,10 @@ import { } from '@/modules/core/graph/generated/graphql' import { StreamRecord } from '@/modules/core/helpers/types' import { - createStream, deleteStream, getStreamFactory, updateStream } from '@/modules/core/repositories/streams' -import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' import { StreamInvalidAccessError, StreamUpdateError @@ -37,99 +35,104 @@ import { isNewResourceAllowed } from '@/modules/core/helpers/token' import { authorizeResolver } from '@/modules/shared' -import { - deleteAllResourceInvitesFactory, - findUserByTargetFactory, - insertInviteAndDeleteOldFactory -} from '@/modules/serverinvites/repositories/serverInvites' +import { deleteAllResourceInvitesFactory } from '@/modules/serverinvites/repositories/serverInvites' import db from '@/db/knex' import { TokenResourceIdentifier, TokenResourceIdentifierType } from '@/modules/core/domain/tokens/types' -import { ProjectEvents, ProjectsEmitter } from '@/modules/core/events/projectsEmitter' +import { + ProjectEvents, + ProjectsEventsEmitter +} from '@/modules/core/events/projectsEmitter' import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' -import { getUsers } from '@/modules/core/repositories/users' -import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' -import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' -import { getEventBus } from '@/modules/shared/services/eventBus' import { ProjectInviteResourceType } from '@/modules/serverinvites/domain/constants' -import { createBranchFactory } from '@/modules/core/repositories/branches' -import { saveActivityFactory } from '@/modules/activitystream/repositories' -import { publish } from '@/modules/shared/utils/subscriptions' +import { + CreateStream, + LegacyCreateStream, + StoreStream +} from '@/modules/core/domain/streams/operations' +import { StoreBranch } from '@/modules/core/domain/branches/operations' -export async function createStreamReturnRecord( - params: (StreamCreateInput | ProjectCreateInput) & { - ownerId: string - ownerResourceAccessRules?: MaybeNullOrUndefined - }, - options?: Partial<{ createActivity: boolean }> -): Promise { - const { ownerId, ownerResourceAccessRules } = params - const { createActivity = true } = options || {} +export const createStreamReturnRecordFactory = + (deps: { + createStream: StoreStream + createBranch: StoreBranch + inviteUsersToProject: ReturnType + addStreamCreatedActivity: ReturnType + projectsEventsEmitter: ProjectsEventsEmitter + }): CreateStream => + async ( + params: (StreamCreateInput | ProjectCreateInput) & { + ownerId: string + ownerResourceAccessRules?: MaybeNullOrUndefined + }, + options?: Partial<{ createActivity: boolean }> + ): Promise => { + const { ownerId, ownerResourceAccessRules } = params + const { createActivity = true } = options || {} - const canCreateStream = isNewResourceAllowed({ - resourceType: TokenResourceIdentifierType.Project, - resourceAccessRules: ownerResourceAccessRules - }) - if (!canCreateStream) { - throw new StreamInvalidAccessError( - 'You do not have the permissions to create a new stream' - ) - } - - const stream = await createStream(params, { ownerId }) - const streamId = stream.id - - // Create a default main branch - await createBranchFactory({ db })({ - name: 'main', - description: 'default branch', - streamId, - authorId: ownerId - }) - - // Invite contributors? - if (!isProjectCreateInput(params) && params.withContributors?.length) { - // TODO: should be injected in the resolver - const getStream = getStreamFactory({ db }) - await inviteUsersToProjectFactory({ - createAndSendInvite: createAndSendInviteFactory({ - findUserByTarget: findUserByTargetFactory(), - insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), - collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ - getStream - }), - buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ - getStream - }), - emitEvent: ({ eventName, payload }) => - getEventBus().emit({ - eventName, - payload - }) - }), - getUsers - })(ownerId, streamId, params.withContributors, ownerResourceAccessRules) - } - - // Save activity - if (createActivity) { - await addStreamCreatedActivityFactory({ - saveActivity: saveActivityFactory({ db }), - publish - })({ - streamId, - input: params, - stream, - creatorId: ownerId + const canCreateStream = isNewResourceAllowed({ + resourceType: TokenResourceIdentifierType.Project, + resourceAccessRules: ownerResourceAccessRules }) + if (!canCreateStream) { + throw new StreamInvalidAccessError( + 'You do not have the permissions to create a new stream' + ) + } + + const stream = await deps.createStream(params, { ownerId }) + const streamId = stream.id + + // Create a default main branch + await deps.createBranch({ + name: 'main', + description: 'default branch', + streamId, + authorId: ownerId + }) + + // Invite contributors? + if (!isProjectCreateInput(params) && params.withContributors?.length) { + // TODO: should be injected in the resolver + await deps.inviteUsersToProject( + ownerId, + streamId, + params.withContributors, + ownerResourceAccessRules + ) + } + + // Save activity + if (createActivity) { + await deps.addStreamCreatedActivity({ + streamId, + input: params, + stream, + creatorId: ownerId + }) + } + + await deps.projectsEventsEmitter(ProjectEvents.Created, { + project: stream, + ownerId + }) + + return stream } - await ProjectsEmitter.emit(ProjectEvents.Created, { project: stream, ownerId }) - - return stream -} +/** + * @deprecated Use createStreamReturnRecordFactory() + */ +export const legacyCreateStreamFactory = + (deps: { createStreamReturnRecord: CreateStream }): LegacyCreateStream => + async (params) => { + const { id } = await deps.createStreamReturnRecord(params, { + createActivity: false + }) + return id + } /** * Delete stream & notify users (emit events & save activity) diff --git a/packages/server/modules/core/services/streams/onboarding.ts b/packages/server/modules/core/services/streams/onboarding.ts index a71ae917d..cc36386fb 100644 --- a/packages/server/modules/core/services/streams/onboarding.ts +++ b/packages/server/modules/core/services/streams/onboarding.ts @@ -6,10 +6,11 @@ import { import { cloneStream } from '@/modules/core/services/streams/clone' import { StreamRecord } from '@/modules/core/helpers/types' import { logger } from '@/logging/logging' -import { createStreamReturnRecord } from '@/modules/core/services/streams/management' import { getOnboardingBaseProjectFactory } from '@/modules/cross-server-sync/services/onboardingProject' import { + createStreamFactory, getOnboardingBaseStream, + getStreamFactory, updateStream } from '@/modules/core/repositories/streams' import { getUser } from '@/modules/core/services/users' @@ -18,6 +19,23 @@ import { isNewResourceAllowed } from '@/modules/core/helpers/token' import { TokenResourceIdentifierType } from '@/modules/core/graph/generated/graphql' +import { createStreamReturnRecordFactory } from '@/modules/core/services/streams/management' +import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} from '@/modules/serverinvites/repositories/serverInvites' +import { db } from '@/db/knex' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { getEventBus } from '@/modules/shared/services/eventBus' +import { getUsers } from '@/modules/core/repositories/users' +import { createBranchFactory } from '@/modules/core/repositories/branches' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' +import { saveActivityFactory } from '@/modules/activitystream/repositories' +import { publish } from '@/modules/shared/utils/subscriptions' export async function createOnboardingStream( targetUserId: string, @@ -33,6 +51,36 @@ export async function createOnboardingStream( ) } + const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish + }) + const getStream = getStreamFactory({ db }) + const createStreamReturnRecord = createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) + const sourceStream = await getOnboardingBaseProjectFactory({ getOnboardingBaseStream })() diff --git a/packages/server/modules/core/tests/branches.spec.js b/packages/server/modules/core/tests/branches.spec.js index c68bbe0c9..867b4f98d 100644 --- a/packages/server/modules/core/tests/branches.spec.js +++ b/packages/server/modules/core/tests/branches.spec.js @@ -9,7 +9,6 @@ const expect = chai.expect const knex = require('@/db/knex') const { createUser } = require('../services/users') -const { createStream } = require('../services/streams') const { createObject } = require('../services/objects') const { getBranchesByStreamId } = require('../services/branches') @@ -32,7 +31,8 @@ const { const { markBranchStreamUpdated, markCommitStreamUpdated, - getStreamFactory + getStreamFactory, + createStreamFactory } = require('@/modules/core/repositories/streams') const { ModelsEmitter } = require('@/modules/core/events/modelsEmitter') const { @@ -49,6 +49,34 @@ const { addCommitCreatedActivity } = require('@/modules/activitystream/services/commitActivity') const { getObjectFactory } = require('@/modules/core/repositories/objects') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') const db = knex const Commits = () => knex('commits') @@ -89,6 +117,37 @@ const createCommitByBranchName = createCommitByBranchNameFactory({ getBranchById: getBranchByIdFactory({ db }) }) +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) + describe('Branches @core-branches', () => { const user = { name: 'Dimitrie Stefanescu', diff --git a/packages/server/modules/core/tests/commits.spec.js b/packages/server/modules/core/tests/commits.spec.js index bc5a0f20e..998a9c277 100644 --- a/packages/server/modules/core/tests/commits.spec.js +++ b/packages/server/modules/core/tests/commits.spec.js @@ -4,7 +4,6 @@ const expect = require('chai').expect const { beforeEachContext } = require('@/test/hooks') const { createUser } = require('../services/users') -const { createStream } = require('../services/streams') const { createObject } = require('../services/objects') const { @@ -47,7 +46,8 @@ const { const { markCommitStreamUpdated, getStreamFactory, - getCommitStreamFactory + getCommitStreamFactory, + createStreamFactory } = require('@/modules/core/repositories/streams') const { addCommitDeletedActivity, @@ -56,6 +56,34 @@ const { } = require('@/modules/activitystream/services/commitActivity') const { VersionsEmitter } = require('@/modules/core/events/versionsEmitter') const { getObjectFactory } = require('@/modules/core/repositories/objects') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') const getCommitStream = getCommitStreamFactory({ db }) const getStream = getStreamFactory({ db }) @@ -107,6 +135,37 @@ const updateCommitAndNotify = updateCommitAndNotifyFactory({ }) const getStreamCommitCount = getStreamCommitCountFactory({ db }) +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) + describe('Commits @core-commits', () => { const user = { name: 'Dimitrie Stefanescu', diff --git a/packages/server/modules/core/tests/favoriteStreams.spec.js b/packages/server/modules/core/tests/favoriteStreams.spec.js index 5780cb84d..909eb3c89 100644 --- a/packages/server/modules/core/tests/favoriteStreams.spec.js +++ b/packages/server/modules/core/tests/favoriteStreams.spec.js @@ -3,7 +3,6 @@ const expect = require('chai').expect const { buildApolloServer } = require('@/app') const { StreamFavorites, Streams, Users } = require('@/modules/core/dbSchema') -const { createStream } = require('@/modules/core/services/streams') const { createUser } = require('@/modules/core/services/users') const { truncateTables } = require('@/test/hooks') const { gql } = require('graphql-tag') @@ -13,6 +12,72 @@ const { createTestContext, executeOperation } = require('@/test/graphqlHelper') +const { + getStreamFactory, + createStreamFactory +} = require('@/modules/core/repositories/streams') +const { db } = require('@/db/knex') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { createBranchFactory } = require('@/modules/core/repositories/branches') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') + +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) /** * Cleaning up relevant tables diff --git a/packages/server/modules/core/tests/generic.spec.js b/packages/server/modules/core/tests/generic.spec.js index cce282b0e..72d799d3c 100644 --- a/packages/server/modules/core/tests/generic.spec.js +++ b/packages/server/modules/core/tests/generic.spec.js @@ -10,7 +10,6 @@ const envHelperMock = mockRequireModule( const expect = require('chai').expect const { beforeEachContext } = require('@/test/hooks') -const { createStream } = require('@/modules/core/services/streams') const { createUser } = require('@/modules/core/services/users') const { validateScopes, authorizeResolver } = require('@/modules/shared') @@ -18,6 +17,72 @@ const { buildContext } = require('@/modules/shared/middleware') const { Roles, Scopes } = require('@speckle/shared') const { throwForNotHavingServerRole } = require('@/modules/shared/authz') const { ForbiddenError } = require('@/modules/shared/errors') +const { + getStreamFactory, + createStreamFactory +} = require('@/modules/core/repositories/streams') +const { db } = require('@/db/knex') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { createBranchFactory } = require('@/modules/core/repositories/branches') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') + +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) describe('Generic AuthN & AuthZ controller tests', () => { before(async () => { diff --git a/packages/server/modules/core/tests/objects.spec.js b/packages/server/modules/core/tests/objects.spec.js index c663a873b..320c86527 100644 --- a/packages/server/modules/core/tests/objects.spec.js +++ b/packages/server/modules/core/tests/objects.spec.js @@ -8,7 +8,6 @@ const { beforeEachContext } = require('@/test/hooks') const { getAnIdForThisOnePlease } = require('@/test/helpers') const { createUser } = require('../services/users') -const { createStream } = require('../services/streams') const { createObject, createObjects, @@ -19,6 +18,40 @@ const { getObjectChildrenQuery, getObjectChildrenStream } = require('../services/objects') +const { + getStreamFactory, + createStreamFactory +} = require('@/modules/core/repositories/streams') +const { db } = require('@/db/knex') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { createBranchFactory } = require('@/modules/core/repositories/branches') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') const sampleCommit = JSON.parse(`{ "Objects": [ @@ -43,6 +76,38 @@ const sampleObject = JSON.parse(`{ "speckleType": "Tests.Polyline" }`) +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) + describe('Objects @core-objects', () => { const userOne = { name: 'Dimitrie Stefanescu', diff --git a/packages/server/modules/core/tests/rest.spec.js b/packages/server/modules/core/tests/rest.spec.js index e57d44cd2..fb881dc27 100644 --- a/packages/server/modules/core/tests/rest.spec.js +++ b/packages/server/modules/core/tests/rest.spec.js @@ -10,8 +10,73 @@ const { createManyObjects } = require('@/test/helpers') const { createUser } = require('../services/users') const { createPersonalAccessToken } = require('../services/tokens') -const { createStream } = require('../services/streams') const { Scopes } = require('@speckle/shared') +const { + getStreamFactory, + createStreamFactory +} = require('@/modules/core/repositories/streams') +const { db } = require('@/db/knex') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { createBranchFactory } = require('@/modules/core/repositories/branches') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') + +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) describe('Upload/Download Routes @api-rest', () => { const userA = { diff --git a/packages/server/modules/core/tests/streams.spec.ts b/packages/server/modules/core/tests/streams.spec.ts index f4a7e89f0..34f516f2f 100644 --- a/packages/server/modules/core/tests/streams.spec.ts +++ b/packages/server/modules/core/tests/streams.spec.ts @@ -1,6 +1,5 @@ import { expect } from 'chai' import { - createStream, updateStream, deleteStream, getStreamUsers, @@ -28,6 +27,7 @@ import { } from '@/test/speckle-helpers/streamHelper' import { StreamWithOptionalRole, + createStreamFactory, getStreamFactory, markBranchStreamUpdated, markCommitStreamUpdated, @@ -73,6 +73,24 @@ import { import { VersionsEmitter } from '@/modules/core/events/versionsEmitter' import { addCommitCreatedActivity } from '@/modules/activitystream/services/commitActivity' import { getObjectFactory } from '@/modules/core/repositories/objects' +import { + createStreamReturnRecordFactory, + legacyCreateStreamFactory +} from '@/modules/core/services/streams/management' +import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} from '@/modules/serverinvites/repositories/serverInvites' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { getEventBus } from '@/modules/shared/services/eventBus' +import { getUsers } from '@/modules/core/repositories/users' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' +import { saveActivityFactory } from '@/modules/activitystream/repositories' +import { publish } from '@/modules/shared/utils/subscriptions' const getStream = getStreamFactory({ db }) const getStreamBranchByName = getStreamBranchByNameFactory({ db }) @@ -105,6 +123,37 @@ const createCommitByBranchName = createCommitByBranchNameFactory({ getBranchById: getBranchByIdFactory({ db }) }) +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) + describe('Streams @core-streams', () => { const userOne: BasicTestUser = { name: 'Dimitrie Stefanescu', diff --git a/packages/server/modules/core/tests/users.spec.js b/packages/server/modules/core/tests/users.spec.js index 98ee10d2d..e1d2f150f 100644 --- a/packages/server/modules/core/tests/users.spec.js +++ b/packages/server/modules/core/tests/users.spec.js @@ -21,7 +21,7 @@ const { validateToken, getUserTokens } = require('../services/tokens') -const { grantPermissionsStream, createStream } = require('../services/streams') +const { grantPermissionsStream } = require('../services/streams') const { getBranchesByStreamId } = require('../services/branches') @@ -50,13 +50,42 @@ const { } = require('@/modules/core/services/commit/management') const { markCommitStreamUpdated, - getStreamFactory + getStreamFactory, + createStreamFactory } = require('@/modules/core/repositories/streams') const { VersionsEmitter } = require('@/modules/core/events/versionsEmitter') const { addCommitCreatedActivity } = require('@/modules/activitystream/services/commitActivity') const { getObjectFactory } = require('@/modules/core/repositories/objects') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') const getStream = getStreamFactory({ db }) const createBranch = createBranchFactory({ db }) @@ -81,6 +110,37 @@ const createCommitByBranchName = createCommitByBranchNameFactory({ getBranchById: getBranchByIdFactory({ db }) }) +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) + describe('Actors & Tokens @user-services', () => { const myTestActor = { name: 'Dimitrie Stefanescu', diff --git a/packages/server/modules/core/tests/usersAdminList.spec.ts b/packages/server/modules/core/tests/usersAdminList.spec.ts index 3119416ef..77533b997 100644 --- a/packages/server/modules/core/tests/usersAdminList.spec.ts +++ b/packages/server/modules/core/tests/usersAdminList.spec.ts @@ -1,7 +1,6 @@ import { ServerInvites, Streams, Users } from '@/modules/core/dbSchema' import { truncateTables } from '@/test/hooks' import { createUser } from '@/modules/core/services/users' -import { createStream } from '@/modules/core/services/streams' import { times, clamp } from 'lodash' import { createStreamInviteDirectly } from '@/test/speckle-helpers/inviteHelper' import { getAdminUsersList } from '@/test/graphql/users' @@ -11,10 +10,65 @@ import { expect } from 'chai' import { Optional } from '@/modules/shared/helpers/typeHelper' import { wait } from '@speckle/shared' import { createAuthedTestContext, ServerAndContext } from '@/test/graphqlHelper' +import { + createStreamFactory, + getStreamFactory +} from '@/modules/core/repositories/streams' +import { db } from '@/db/knex' +import { + createStreamReturnRecordFactory, + legacyCreateStreamFactory +} from '@/modules/core/services/streams/management' +import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} from '@/modules/serverinvites/repositories/serverInvites' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { getEventBus } from '@/modules/shared/services/eventBus' +import { getUsers } from '@/modules/core/repositories/users' +import { createBranchFactory } from '@/modules/core/repositories/branches' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' +import { saveActivityFactory } from '@/modules/activitystream/repositories' +import { publish } from '@/modules/shared/utils/subscriptions' // To ensure that the invites are created in the correct order, we need to wait a bit between each creation const WAIT_TIMEOUT = 5 +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) const createInviteDirectly = createStreamInviteDirectly function randomEl(array: T[]): T { diff --git a/packages/server/modules/cross-server-sync/index.ts b/packages/server/modules/cross-server-sync/index.ts index 4bd195b59..be96d47fa 100644 --- a/packages/server/modules/cross-server-sync/index.ts +++ b/packages/server/modules/cross-server-sync/index.ts @@ -1,11 +1,13 @@ import { db } from '@/db/knex' import { moduleLogger, crossServerSyncLogger } from '@/logging/logging' +import { saveActivityFactory } from '@/modules/activitystream/repositories' import { addBranchCreatedActivity } from '@/modules/activitystream/services/branchActivity' import { addCommentCreatedActivity, addReplyAddedActivity } from '@/modules/activitystream/services/commentActivity' import { addCommitCreatedActivity } from '@/modules/activitystream/services/commitActivity' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' import { getBlobsFactory } from '@/modules/blobstorage/repositories' import { CommentsEmitter } from '@/modules/comments/events/emitter' import { @@ -20,6 +22,7 @@ import { createCommentReplyAndNotifyFactory, createCommentThreadAndNotifyFactory } from '@/modules/comments/services/management' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' import { VersionsEmitter } from '@/modules/core/events/versionsEmitter' import { createBranchFactory, @@ -41,13 +44,14 @@ import { getStreamObjectsFactory } from '@/modules/core/repositories/objects' import { + createStreamFactory, getOnboardingBaseStream, getStreamCollaboratorsFactory, getStreamFactory, markCommitStreamUpdated, markOnboardingBaseStream } from '@/modules/core/repositories/streams' -import { getFirstAdmin, getUser } from '@/modules/core/repositories/users' +import { getFirstAdmin, getUser, getUsers } from '@/modules/core/repositories/users' import { createBranchAndNotifyFactory } from '@/modules/core/services/branch/management' import { createCommitByBranchIdFactory } from '@/modules/core/services/commit/management' import { @@ -55,11 +59,21 @@ import { getViewerResourceItemsUngroupedFactory } from '@/modules/core/services/commit/viewerResources' import { createObject } from '@/modules/core/services/objects' -import { createStreamReturnRecord } from '@/modules/core/services/streams/management' +import { createStreamReturnRecordFactory } from '@/modules/core/services/streams/management' import { downloadCommitFactory } from '@/modules/cross-server-sync/services/commit' import { ensureOnboardingProjectFactory } from '@/modules/cross-server-sync/services/onboardingProject' import { downloadProjectFactory } from '@/modules/cross-server-sync/services/project' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} from '@/modules/serverinvites/repositories/serverInvites' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' import { SpeckleModule } from '@/modules/shared/helpers/typeHelper' +import { getEventBus } from '@/modules/shared/services/eventBus' +import { publish } from '@/modules/shared/utils/subscriptions' const crossServerSyncModule: SpeckleModule = { init() { @@ -117,6 +131,33 @@ const crossServerSyncModule: SpeckleModule = { addCommitCreatedActivity }) + const createStreamReturnRecord = createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity: addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish + }), + projectsEventsEmitter: ProjectsEmitter.emit + }) const ensureOnboardingProject = ensureOnboardingProjectFactory({ getOnboardingBaseStream, getFirstAdmin, diff --git a/packages/server/modules/cross-server-sync/services/project.ts b/packages/server/modules/cross-server-sync/services/project.ts index bdbd7b91f..a28cdc929 100644 --- a/packages/server/modules/cross-server-sync/services/project.ts +++ b/packages/server/modules/cross-server-sync/services/project.ts @@ -10,7 +10,6 @@ import { import { CrossSyncProjectMetadataQuery } from '@/modules/cross-server-sync/graph/generated/graphql' import { omit } from 'lodash' import { getFrontendOrigin } from '@/modules/shared/helpers/envHelper' -import { createStreamReturnRecord } from '@/modules/core/services/streams/management' import { DownloadCommit, DownloadProject @@ -19,6 +18,7 @@ import { CreateBranchAndNotify, GetStreamBranchByName } from '@/modules/core/domain/branches/operations' +import { CreateStream } from '@/modules/core/domain/streams/operations' type ProjectMetadata = Awaited> @@ -193,7 +193,7 @@ const importVersionsFactory = } type DownloadProjectDeps = { - createStreamReturnRecord: typeof createStreamReturnRecord + createStreamReturnRecord: CreateStream } & GetLocalResourcesDeps & ImportVersionsDeps diff --git a/packages/server/modules/fileuploads/tests/fileuploads.integration.spec.ts b/packages/server/modules/fileuploads/tests/fileuploads.integration.spec.ts index 9f73fb438..41948a74d 100644 --- a/packages/server/modules/fileuploads/tests/fileuploads.integration.spec.ts +++ b/packages/server/modules/fileuploads/tests/fileuploads.integration.spec.ts @@ -4,7 +4,6 @@ import { expect } from 'chai' import { beforeEachContext, initializeTestServer } from '@/test/hooks' import { createUser } from '@/modules/core/services/users' -import { createStream } from '@/modules/core/services/streams' import { createToken } from '@/modules/core/services/tokens' import type { Server } from 'http' import type { Express } from 'express' @@ -12,6 +11,62 @@ import request from 'supertest' import { Scopes } from '@/modules/core/helpers/mainConstants' import cryptoRandomString from 'crypto-random-string' import { noErrors } from '@/test/helpers' +import { + createStreamFactory, + getStreamFactory +} from '@/modules/core/repositories/streams' +import { db } from '@/db/knex' +import { + createStreamReturnRecordFactory, + legacyCreateStreamFactory +} from '@/modules/core/services/streams/management' +import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} from '@/modules/serverinvites/repositories/serverInvites' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { getEventBus } from '@/modules/shared/services/eventBus' +import { getUsers } from '@/modules/core/repositories/users' +import { createBranchFactory } from '@/modules/core/repositories/branches' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' +import { saveActivityFactory } from '@/modules/activitystream/repositories' +import { publish } from '@/modules/shared/utils/subscriptions' + +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) describe('FileUploads @fileuploads', () => { let server: Server diff --git a/packages/server/modules/stats/tests/stats.spec.ts b/packages/server/modules/stats/tests/stats.spec.ts index 6ba34b13b..56c56bfd3 100644 --- a/packages/server/modules/stats/tests/stats.spec.ts +++ b/packages/server/modules/stats/tests/stats.spec.ts @@ -2,7 +2,6 @@ import { expect } from 'chai' import { createUser } from '@/modules/core/services/users' import { createPersonalAccessToken } from '@/modules/core/services/tokens' -import { createStream } from '@/modules/core/services/streams' import { createObjects } from '@/modules/core/services/objects' import { beforeEachContext, initializeTestServer } from '@/test/hooks' import { createManyObjects } from '@/test/helpers' @@ -31,14 +30,37 @@ import { insertStreamCommitsFactory } from '@/modules/core/repositories/commits' import { + createBranchFactory, getBranchByIdFactory, getStreamBranchByNameFactory, markCommitBranchUpdatedFactory } from '@/modules/core/repositories/branches' -import { markCommitStreamUpdated } from '@/modules/core/repositories/streams' +import { + createStreamFactory, + getStreamFactory, + markCommitStreamUpdated +} from '@/modules/core/repositories/streams' import { VersionsEmitter } from '@/modules/core/events/versionsEmitter' import { addCommitCreatedActivity } from '@/modules/activitystream/services/commitActivity' import { getObjectFactory } from '@/modules/core/repositories/objects' +import { + createStreamReturnRecordFactory, + legacyCreateStreamFactory +} from '@/modules/core/services/streams/management' +import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} from '@/modules/serverinvites/repositories/serverInvites' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { getEventBus } from '@/modules/shared/services/eventBus' +import { getUsers } from '@/modules/core/repositories/users' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' +import { saveActivityFactory } from '@/modules/activitystream/repositories' +import { publish } from '@/modules/shared/utils/subscriptions' const getObject = getObjectFactory({ db }) const createCommitByBranchId = createCommitByBranchIdFactory({ @@ -59,6 +81,38 @@ const createCommitByBranchName = createCommitByBranchNameFactory({ getBranchById: getBranchByIdFactory({ db }) }) +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) + const params = { numUsers: 25, numStreams: 30, numObjects: 100, numCommits: 100 } describe('Server stats services @stats-services', function () { diff --git a/packages/server/modules/webhooks/tests/cleanup.spec.ts b/packages/server/modules/webhooks/tests/cleanup.spec.ts index e9521484a..e691cab8c 100644 --- a/packages/server/modules/webhooks/tests/cleanup.spec.ts +++ b/packages/server/modules/webhooks/tests/cleanup.spec.ts @@ -1,10 +1,32 @@ -import knex from '@/db/knex' +import knex, { db } from '@/db/knex' +import { saveActivityFactory } from '@/modules/activitystream/repositories' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' import { createRandomEmail, createRandomPassword } from '@/modules/core/helpers/testHelpers' -import { createStream } from '@/modules/core/services/streams' +import { createBranchFactory } from '@/modules/core/repositories/branches' +import { + createStreamFactory, + getStreamFactory +} from '@/modules/core/repositories/streams' +import { getUsers } from '@/modules/core/repositories/users' +import { + createStreamReturnRecordFactory, + legacyCreateStreamFactory +} from '@/modules/core/services/streams/management' import { createUser } from '@/modules/core/services/users' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} from '@/modules/serverinvites/repositories/serverInvites' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' +import { getEventBus } from '@/modules/shared/services/eventBus' +import { publish } from '@/modules/shared/utils/subscriptions' import { cleanOrphanedWebhookConfigs } from '@/modules/webhooks/services/cleanup' import { truncateTables } from '@/test/hooks' import { expect } from 'chai' @@ -16,6 +38,38 @@ const WEBHOOKS_EVENTS_TABLE = 'webhooks_events' const WebhooksConfig = () => knex(WEBHOOKS_CONFIG_TABLE) const randomId = () => crs({ length: 10 }) +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) + const countWebhooks = async () => { const [{ count }] = await WebhooksConfig().count() return parseInt(count as string) diff --git a/packages/server/modules/webhooks/tests/webhooks.spec.js b/packages/server/modules/webhooks/tests/webhooks.spec.js index 7674e6380..b7919e239 100644 --- a/packages/server/modules/webhooks/tests/webhooks.spec.js +++ b/packages/server/modules/webhooks/tests/webhooks.spec.js @@ -10,7 +10,7 @@ const { const { noErrors } = require('@/test/helpers') const { createPersonalAccessToken } = require('../../core/services/tokens') const { createUser } = require('../../core/services/users') -const { createStream, grantPermissionsStream } = require('../../core/services/streams') +const { grantPermissionsStream } = require('../../core/services/streams') const { Scopes, Roles } = require('@speckle/shared') const { createWebhookConfigFactory, @@ -31,14 +31,75 @@ const { } = require('@/modules/webhooks/services/webhooks') const { Users, Streams } = require('@/modules/core/dbSchema') const { getServerInfo } = require('@/modules/core/services/generic') -const { getUser } = require('@/modules/core/repositories/users') -const { getStreamFactory } = require('@/modules/core/repositories/streams') +const { getUser, getUsers } = require('@/modules/core/repositories/users') +const { + getStreamFactory, + createStreamFactory +} = require('@/modules/core/repositories/streams') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { createBranchFactory } = require('@/modules/core/repositories/branches') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) const getStream = getStreamFactory({ db }) const updateWebhook = updateWebhookFactory({ updateWebhookConfig: updateWebhookConfigFactory({ db }) }) const getStreamWebhooks = getStreamWebhooksFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) describe('Webhooks @webhooks', () => { const getWebhook = getWebhookByIdFactory({ db }) diff --git a/packages/server/scripts/streamObjects.js b/packages/server/scripts/streamObjects.js index 5a4b1e254..4a104577f 100644 --- a/packages/server/scripts/streamObjects.js +++ b/packages/server/scripts/streamObjects.js @@ -1,7 +1,6 @@ require('../bootstrap') const { getUserByEmail } = require('@/modules/core/services/users') const { createPersonalAccessToken } = require('@/modules/core/services/tokens') -const { createStream } = require('@/modules/core/services/streams') const { createManyObjects } = require('@/test/helpers') const { fetch } = require('undici') @@ -10,6 +9,72 @@ const request = require('supertest') const { exit } = require('yargs') const { logger } = require('@/logging/logging') const { Scopes } = require('@speckle/shared') +const { + getStreamFactory, + createStreamFactory +} = require('@/modules/core/repositories/streams') +const { db } = require('@/db/knex') +const { + legacyCreateStreamFactory, + createStreamReturnRecordFactory +} = require('@/modules/core/services/streams/management') +const { + inviteUsersToProjectFactory +} = require('@/modules/serverinvites/services/projectInviteManagement') +const { + createAndSendInviteFactory +} = require('@/modules/serverinvites/services/creation') +const { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} = require('@/modules/serverinvites/repositories/serverInvites') +const { + collectAndValidateCoreTargetsFactory +} = require('@/modules/serverinvites/services/coreResourceCollection') +const { + buildCoreInviteEmailContentsFactory +} = require('@/modules/serverinvites/services/coreEmailContents') +const { getEventBus } = require('@/modules/shared/services/eventBus') +const { getUsers } = require('@/modules/core/repositories/users') +const { createBranchFactory } = require('@/modules/core/repositories/branches') +const { ProjectsEmitter } = require('@/modules/core/events/projectsEmitter') +const { + addStreamCreatedActivityFactory +} = require('@/modules/activitystream/services/streamActivity') +const { saveActivityFactory } = require('@/modules/activitystream/repositories') +const { publish } = require('@/modules/shared/utils/subscriptions') + +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) const main = async () => { const testStream = { diff --git a/packages/server/test/speckle-helpers/streamHelper.ts b/packages/server/test/speckle-helpers/streamHelper.ts index 503d87bf7..a21eca173 100644 --- a/packages/server/test/speckle-helpers/streamHelper.ts +++ b/packages/server/test/speckle-helpers/streamHelper.ts @@ -1,12 +1,67 @@ +import { db } from '@/db/knex' +import { saveActivityFactory } from '@/modules/activitystream/repositories' +import { addStreamCreatedActivityFactory } from '@/modules/activitystream/services/streamActivity' import { StreamAcl } from '@/modules/core/dbSchema' +import { ProjectsEmitter } from '@/modules/core/events/projectsEmitter' import { StreamAclRecord, StreamRecord } from '@/modules/core/helpers/types' -import { createStream } from '@/modules/core/services/streams' +import { createBranchFactory } from '@/modules/core/repositories/branches' +import { + createStreamFactory, + getStreamFactory +} from '@/modules/core/repositories/streams' +import { getUsers } from '@/modules/core/repositories/users' +import { + createStreamReturnRecordFactory, + legacyCreateStreamFactory +} from '@/modules/core/services/streams/management' import { removeStreamCollaborator } from '@/modules/core/services/streams/streamAccessService' +import { + findUserByTargetFactory, + insertInviteAndDeleteOldFactory +} from '@/modules/serverinvites/repositories/serverInvites' +import { buildCoreInviteEmailContentsFactory } from '@/modules/serverinvites/services/coreEmailContents' +import { collectAndValidateCoreTargetsFactory } from '@/modules/serverinvites/services/coreResourceCollection' +import { createAndSendInviteFactory } from '@/modules/serverinvites/services/creation' +import { inviteUsersToProjectFactory } from '@/modules/serverinvites/services/projectInviteManagement' import { Nullable } from '@/modules/shared/helpers/typeHelper' +import { getEventBus } from '@/modules/shared/services/eventBus' +import { publish } from '@/modules/shared/utils/subscriptions' import { BasicTestUser } from '@/test/authHelper' import { ensureError } from '@speckle/shared' import { omit } from 'lodash' +const addStreamCreatedActivity = addStreamCreatedActivityFactory({ + saveActivity: saveActivityFactory({ db }), + publish +}) +const getStream = getStreamFactory({ db }) +const createStream = legacyCreateStreamFactory({ + createStreamReturnRecord: createStreamReturnRecordFactory({ + inviteUsersToProject: inviteUsersToProjectFactory({ + createAndSendInvite: createAndSendInviteFactory({ + findUserByTarget: findUserByTargetFactory(), + insertInviteAndDeleteOld: insertInviteAndDeleteOldFactory({ db }), + collectAndValidateResourceTargets: collectAndValidateCoreTargetsFactory({ + getStream + }), + buildInviteEmailContents: buildCoreInviteEmailContentsFactory({ + getStream + }), + emitEvent: ({ eventName, payload }) => + getEventBus().emit({ + eventName, + payload + }) + }), + getUsers + }), + createStream: createStreamFactory({ db }), + createBranch: createBranchFactory({ db }), + addStreamCreatedActivity, + projectsEventsEmitter: ProjectsEmitter.emit + }) +}) + export type BasicTestStream = { name: string isPublic: boolean