From dfae03b63993ac7e66a199e9e38492fad7a57652 Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Wed, 24 Jul 2024 17:36:12 +0300 Subject: [PATCH 01/27] (almost) atomic profile creation --- .../common/location/location.service.ts | 5 ++- src/domain/common/profile/profile.service.ts | 34 ++++++------------- .../common/reference/reference.service.ts | 6 ++-- src/domain/common/tagset/tagset.service.ts | 7 ++-- .../storage-bucket/storage.bucket.service.ts | 14 ++++---- 5 files changed, 24 insertions(+), 42 deletions(-) diff --git a/src/domain/common/location/location.service.ts b/src/domain/common/location/location.service.ts index 25ed04a930..c01ffd826e 100644 --- a/src/domain/common/location/location.service.ts +++ b/src/domain/common/location/location.service.ts @@ -14,9 +14,8 @@ export class LocationService { private locationRepository: Repository ) {} - async createLocation(locationData?: CreateLocationInput): Promise { - const location = Location.create({ ...locationData }); - return await this.locationRepository.save(location); + public createLocation(locationData?: CreateLocationInput): ILocation { + return Location.create({ ...locationData }); } async removeLocation(location: ILocation): Promise { return await this.locationRepository.remove(location as Location); diff --git a/src/domain/common/profile/profile.service.ts b/src/domain/common/profile/profile.service.ts index 3ef4589d59..7c21b01e74 100644 --- a/src/domain/common/profile/profile.service.ts +++ b/src/domain/common/profile/profile.service.ts @@ -59,41 +59,27 @@ export class ProfileService { type: profileType, }); profile.authorization = new AuthorizationPolicy(); + // the next statement fails if it's not saved profile.storageBucket = await this.storageBucketService.createStorageBucket( { storageAggregator: storageAggregator } ); profile.visuals = []; - profile.location = await this.locationService.createLocation( + profile.location = this.locationService.createLocation( profileData?.location ); - profile.references = []; - if (profileData?.referencesData) { - for (const referenceData of profileData.referencesData) { - const reference = - await this.referenceService.createReference(referenceData); - profile.references.push(reference); - } - } - await this.profileRepository.save(profile); - this.logger.verbose?.( - `Created new profile with id: ${profile.id}`, - LogContext.COMMUNITY + const newReferences = profileData?.referencesData?.map( + this.referenceService.createReference ); + profile.references = newReferences ?? []; - profile.tagsets = []; - if (profileData?.tagsets) { - for (const tagsetData of profileData?.tagsets) { - const tagset = await this.tagsetService.createTagsetWithName( - profile.tagsets, - tagsetData - ); - profile.tagsets.push(tagset); - } - } + const tagsetsFromInput = profileData?.tagsets?.map(tagsetData => + this.tagsetService.createTagsetWithName([], tagsetData) + ); + profile.tagsets = tagsetsFromInput ?? []; - return await this.save(profile); + return profile; } async updateProfile( diff --git a/src/domain/common/reference/reference.service.ts b/src/domain/common/reference/reference.service.ts index bbc7ae679f..4471647e24 100644 --- a/src/domain/common/reference/reference.service.ts +++ b/src/domain/common/reference/reference.service.ts @@ -21,16 +21,14 @@ export class ReferenceService { private referenceRepository: Repository ) {} - async createReference( - referenceInput: CreateReferenceInput - ): Promise { + public createReference(referenceInput: CreateReferenceInput): IReference { const reference = new Reference( referenceInput.name, referenceInput.uri || '', referenceInput.description ); reference.authorization = new AuthorizationPolicy(); - await this.referenceRepository.save(reference); + return reference; } diff --git a/src/domain/common/tagset/tagset.service.ts b/src/domain/common/tagset/tagset.service.ts index aa0603db4d..54e960da0b 100644 --- a/src/domain/common/tagset/tagset.service.ts +++ b/src/domain/common/tagset/tagset.service.ts @@ -1,3 +1,4 @@ +import { some } from 'lodash'; import { Inject, Injectable, LoggerService } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; @@ -233,10 +234,10 @@ export class TagsetService { return tagset; } - async createTagsetWithName( + public createTagsetWithName( existingTagsets: ITagset[], tagsetData: CreateTagsetInput - ): Promise { + ): ITagset { // Check if the group already exists, if so log a warning if (this.hasTagsetWithName(existingTagsets, tagsetData.name)) { throw new ValidationException( @@ -245,7 +246,7 @@ export class TagsetService { ); } - return await this.createTagset(tagsetData); + return Tagset.create({ ...tagsetData }); } async save(tagset: ITagset): Promise { diff --git a/src/domain/storage/storage-bucket/storage.bucket.service.ts b/src/domain/storage/storage-bucket/storage.bucket.service.ts index 8d9ae6efb2..47169b609f 100644 --- a/src/domain/storage/storage-bucket/storage.bucket.service.ts +++ b/src/domain/storage/storage-bucket/storage.bucket.service.ts @@ -51,7 +51,7 @@ export class StorageBucketService { private profileRepository: Repository ) {} - public async createStorageBucket( + public createStorageBucket( storageBucketData: CreateStorageBucketInput ): Promise { const storage: IStorageBucket = new StorageBucket(); @@ -63,7 +63,7 @@ export class StorageBucketService { storageBucketData?.maxFileSize || this.DEFAULT_MAX_ALLOWED_FILE_SIZE; storage.storageAggregator = storageBucketData.storageAggregator; - return await this.storageBucketRepository.save(storage); + return this.storageBucketRepository.save(storage); } async deleteStorageBucket(storageID: string): Promise { @@ -188,9 +188,8 @@ export class StorageBucketService { /* just consume */ } - const document = await this.documentService.createDocument( - createDocumentInput - ); + const document = + await this.documentService.createDocument(createDocumentInput); document.storageBucket = storage; this.logger.verbose?.( @@ -215,9 +214,8 @@ export class StorageBucketService { LogContext.DOCUMENT ); - const documentForReference = await this.documentService.getDocumentFromURL( - uri - ); + const documentForReference = + await this.documentService.getDocumentFromURL(uri); try { const newDocument = await this.uploadFileAsDocument( From faa0cefc733e36d5cea844584ee648962ad7140b Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Thu, 25 Jul 2024 15:44:46 +0300 Subject: [PATCH 02/27] atomic creation of callout contribution --- .../callout.contribution.service.ts | 5 ++-- src/domain/collaboration/post/post.service.ts | 9 ++---- .../profile/profile.resolver.mutations.ts | 2 +- src/domain/common/profile/profile.service.ts | 19 +++++++------ src/domain/common/visual/visual.service.ts | 28 +++++++++++-------- .../common/whiteboard/whiteboard.service.ts | 7 ++--- src/domain/communication/room/room.service.ts | 2 +- 7 files changed, 35 insertions(+), 37 deletions(-) diff --git a/src/domain/collaboration/callout-contribution/callout.contribution.service.ts b/src/domain/collaboration/callout-contribution/callout.contribution.service.ts index a9bdccaa16..3b380944f3 100644 --- a/src/domain/collaboration/callout-contribution/callout.contribution.service.ts +++ b/src/domain/collaboration/callout-contribution/callout.contribution.service.ts @@ -42,6 +42,7 @@ export class CalloutContributionService { ); contribution.authorization = new AuthorizationPolicy(); + contribution.createdBy = userID; const { post, whiteboard, link } = calloutContributionData; @@ -70,8 +71,6 @@ export class CalloutContributionService { ); } - contribution.createdBy = userID; - if (link) { this.validateContributionType( contributionPolicy, @@ -84,7 +83,7 @@ export class CalloutContributionService { ); } - return await this.save(contribution); + return contribution; } private validateContributionType( diff --git a/src/domain/collaboration/post/post.service.ts b/src/domain/collaboration/post/post.service.ts index f887b1b4d5..aead9bcc69 100644 --- a/src/domain/collaboration/post/post.service.ts +++ b/src/domain/collaboration/post/post.service.ts @@ -40,11 +40,8 @@ export class PostService { ProfileType.POST, storageAggregator ); - await this.profileService.addVisualOnProfile( - post.profile, - VisualType.BANNER - ); - await this.profileService.addVisualOnProfile(post.profile, VisualType.CARD); + this.profileService.addVisualOnProfile(post.profile, VisualType.BANNER); + this.profileService.addVisualOnProfile(post.profile, VisualType.CARD); await this.profileService.addTagsetOnProfile(post.profile, { name: TagsetReservedName.DEFAULT, tags: postInput.tags || [], @@ -57,7 +54,7 @@ export class PostService { RoomType.POST ); - return await this.savePost(post); + return post; } public async deletePost(postId: string): Promise { diff --git a/src/domain/common/profile/profile.resolver.mutations.ts b/src/domain/common/profile/profile.resolver.mutations.ts index b23e75458f..1dc2ae683f 100644 --- a/src/domain/common/profile/profile.resolver.mutations.ts +++ b/src/domain/common/profile/profile.resolver.mutations.ts @@ -41,7 +41,7 @@ export class ProfileResolverMutations { const profile = await this.profileService.getProfileOrFail( tagsetData.profileID ); - await this.authorizationService.grantAccessOrFail( + this.authorizationService.grantAccessOrFail( agentInfo, profile.authorization, AuthorizationPrivilege.CREATE, diff --git a/src/domain/common/profile/profile.service.ts b/src/domain/common/profile/profile.service.ts index 7c21b01e74..cc7dbdd6c5 100644 --- a/src/domain/common/profile/profile.service.ts +++ b/src/domain/common/profile/profile.service.ts @@ -185,7 +185,7 @@ export class ProfileService { return await this.profileRepository.save(profile); } - async addVisualOnProfile( + public addVisualOnProfile( profile: IProfile, visualType: VisualType, url?: string @@ -193,16 +193,16 @@ export class ProfileService { let visual: IVisual; switch (visualType) { case VisualType.AVATAR: - visual = await this.visualService.createVisualAvatar(); + visual = this.visualService.createVisualAvatar(); break; case VisualType.BANNER: - visual = await this.visualService.createVisualBanner(); + visual = this.visualService.createVisualBanner(); break; case VisualType.CARD: - visual = await this.visualService.createVisualCard(); + visual = this.visualService.createVisualCard(); break; case VisualType.BANNER_WIDE: - visual = await this.visualService.createVisualBannerWide(); + visual = this.visualService.createVisualBannerWide(); break; default: @@ -226,15 +226,16 @@ export class ProfileService { profile: IProfile, tagsetData: CreateTagsetInput ): Promise { - profile.tagsets = await this.getTagsets(profile); - const tagset = await this.tagsetService.createTagsetWithName( + if (!profile.tagsets) { + profile.tagsets = await this.getTagsets(profile); + } + + const tagset = this.tagsetService.createTagsetWithName( profile.tagsets, tagsetData ); profile.tagsets.push(tagset); - await this.profileRepository.save(profile); - return tagset; } diff --git a/src/domain/common/visual/visual.service.ts b/src/domain/common/visual/visual.service.ts index 8a81501b7a..25cca84a1a 100644 --- a/src/domain/common/visual/visual.service.ts +++ b/src/domain/common/visual/visual.service.ts @@ -32,17 +32,21 @@ export class VisualService { private visualRepository: Repository ) {} - async createVisual( + public createVisual( visualInput: CreateVisualInput, initialUri?: string - ): Promise { + ): IVisual { const visual: IVisual = Visual.create({ ...visualInput, uri: initialUri ?? '', }); + visual.authorization = new AuthorizationPolicy(); - if (initialUri) visual.uri = initialUri; - await this.visualRepository.save(visual); + + if (initialUri) { + visual.uri = initialUri; + } + return visual; } @@ -178,8 +182,8 @@ export class VisualService { ); } - async createVisualBanner(uri?: string): Promise { - return await this.createVisual( + public createVisualBanner(uri?: string): IVisual { + return this.createVisual( { name: 'banner', minWidth: 384, @@ -192,8 +196,8 @@ export class VisualService { ); } - async createVisualCard(uri?: string): Promise { - return await this.createVisual( + public createVisualCard(uri?: string): IVisual { + return this.createVisual( { name: 'card', minWidth: 307, @@ -206,8 +210,8 @@ export class VisualService { ); } - async createVisualBannerWide(uri?: string): Promise { - return await this.createVisual( + public createVisualBannerWide(uri?: string): IVisual { + return this.createVisual( { name: 'bannerWide', minWidth: 640, @@ -220,8 +224,8 @@ export class VisualService { ); } - async createVisualAvatar(): Promise { - return await this.createVisual({ + public createVisualAvatar(): IVisual { + return this.createVisual({ name: 'avatar', minWidth: avatarMinImageSize, maxWidth: avatarMaxImageSize, diff --git a/src/domain/common/whiteboard/whiteboard.service.ts b/src/domain/common/whiteboard/whiteboard.service.ts index 90b5d930bb..0add1d7733 100644 --- a/src/domain/common/whiteboard/whiteboard.service.ts +++ b/src/domain/common/whiteboard/whiteboard.service.ts @@ -73,16 +73,13 @@ export class WhiteboardService { ProfileType.WHITEBOARD, storageAggregator ); - await this.profileService.addVisualOnProfile( - whiteboard.profile, - VisualType.CARD - ); + this.profileService.addVisualOnProfile(whiteboard.profile, VisualType.CARD); await this.profileService.addTagsetOnProfile(whiteboard.profile, { name: TagsetReservedName.DEFAULT, tags: [], }); - return this.save(whiteboard); + return whiteboard; } async getWhiteboardOrFail( diff --git a/src/domain/communication/room/room.service.ts b/src/domain/communication/room/room.service.ts index d39dec08d3..5486a47011 100644 --- a/src/domain/communication/room/room.service.ts +++ b/src/domain/communication/room/room.service.ts @@ -44,7 +44,7 @@ export class RoomService { room.externalRoomID = await this.initializeCommunicationRoom(room); room.messagesCount = 0; room.vcInteractions = []; - return await this.roomRepository.save(room); + return room; } async getRoomOrFail( From 2f795e02cbbcacfe4a1c5cd0ee8b023bfa1d7a8d Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Thu, 25 Jul 2024 15:44:46 +0300 Subject: [PATCH 03/27] atomic creation of callout contribution --- .../callout.contribution.service.ts | 5 ++-- src/domain/collaboration/post/post.service.ts | 9 ++---- .../profile/profile.resolver.mutations.ts | 2 +- src/domain/common/profile/profile.service.ts | 19 +++++++------ src/domain/common/visual/visual.service.ts | 28 +++++++++++-------- .../common/whiteboard/whiteboard.service.ts | 7 ++--- src/domain/communication/room/room.service.ts | 2 +- 7 files changed, 35 insertions(+), 37 deletions(-) diff --git a/src/domain/collaboration/callout-contribution/callout.contribution.service.ts b/src/domain/collaboration/callout-contribution/callout.contribution.service.ts index a9bdccaa16..3b380944f3 100644 --- a/src/domain/collaboration/callout-contribution/callout.contribution.service.ts +++ b/src/domain/collaboration/callout-contribution/callout.contribution.service.ts @@ -42,6 +42,7 @@ export class CalloutContributionService { ); contribution.authorization = new AuthorizationPolicy(); + contribution.createdBy = userID; const { post, whiteboard, link } = calloutContributionData; @@ -70,8 +71,6 @@ export class CalloutContributionService { ); } - contribution.createdBy = userID; - if (link) { this.validateContributionType( contributionPolicy, @@ -84,7 +83,7 @@ export class CalloutContributionService { ); } - return await this.save(contribution); + return contribution; } private validateContributionType( diff --git a/src/domain/collaboration/post/post.service.ts b/src/domain/collaboration/post/post.service.ts index f887b1b4d5..aead9bcc69 100644 --- a/src/domain/collaboration/post/post.service.ts +++ b/src/domain/collaboration/post/post.service.ts @@ -40,11 +40,8 @@ export class PostService { ProfileType.POST, storageAggregator ); - await this.profileService.addVisualOnProfile( - post.profile, - VisualType.BANNER - ); - await this.profileService.addVisualOnProfile(post.profile, VisualType.CARD); + this.profileService.addVisualOnProfile(post.profile, VisualType.BANNER); + this.profileService.addVisualOnProfile(post.profile, VisualType.CARD); await this.profileService.addTagsetOnProfile(post.profile, { name: TagsetReservedName.DEFAULT, tags: postInput.tags || [], @@ -57,7 +54,7 @@ export class PostService { RoomType.POST ); - return await this.savePost(post); + return post; } public async deletePost(postId: string): Promise { diff --git a/src/domain/common/profile/profile.resolver.mutations.ts b/src/domain/common/profile/profile.resolver.mutations.ts index b23e75458f..1dc2ae683f 100644 --- a/src/domain/common/profile/profile.resolver.mutations.ts +++ b/src/domain/common/profile/profile.resolver.mutations.ts @@ -41,7 +41,7 @@ export class ProfileResolverMutations { const profile = await this.profileService.getProfileOrFail( tagsetData.profileID ); - await this.authorizationService.grantAccessOrFail( + this.authorizationService.grantAccessOrFail( agentInfo, profile.authorization, AuthorizationPrivilege.CREATE, diff --git a/src/domain/common/profile/profile.service.ts b/src/domain/common/profile/profile.service.ts index 3ef4589d59..9a947e7f91 100644 --- a/src/domain/common/profile/profile.service.ts +++ b/src/domain/common/profile/profile.service.ts @@ -199,7 +199,7 @@ export class ProfileService { return await this.profileRepository.save(profile); } - async addVisualOnProfile( + public addVisualOnProfile( profile: IProfile, visualType: VisualType, url?: string @@ -207,16 +207,16 @@ export class ProfileService { let visual: IVisual; switch (visualType) { case VisualType.AVATAR: - visual = await this.visualService.createVisualAvatar(); + visual = this.visualService.createVisualAvatar(); break; case VisualType.BANNER: - visual = await this.visualService.createVisualBanner(); + visual = this.visualService.createVisualBanner(); break; case VisualType.CARD: - visual = await this.visualService.createVisualCard(); + visual = this.visualService.createVisualCard(); break; case VisualType.BANNER_WIDE: - visual = await this.visualService.createVisualBannerWide(); + visual = this.visualService.createVisualBannerWide(); break; default: @@ -240,15 +240,16 @@ export class ProfileService { profile: IProfile, tagsetData: CreateTagsetInput ): Promise { - profile.tagsets = await this.getTagsets(profile); - const tagset = await this.tagsetService.createTagsetWithName( + if (!profile.tagsets) { + profile.tagsets = await this.getTagsets(profile); + } + + const tagset = this.tagsetService.createTagsetWithName( profile.tagsets, tagsetData ); profile.tagsets.push(tagset); - await this.profileRepository.save(profile); - return tagset; } diff --git a/src/domain/common/visual/visual.service.ts b/src/domain/common/visual/visual.service.ts index 8a81501b7a..25cca84a1a 100644 --- a/src/domain/common/visual/visual.service.ts +++ b/src/domain/common/visual/visual.service.ts @@ -32,17 +32,21 @@ export class VisualService { private visualRepository: Repository ) {} - async createVisual( + public createVisual( visualInput: CreateVisualInput, initialUri?: string - ): Promise { + ): IVisual { const visual: IVisual = Visual.create({ ...visualInput, uri: initialUri ?? '', }); + visual.authorization = new AuthorizationPolicy(); - if (initialUri) visual.uri = initialUri; - await this.visualRepository.save(visual); + + if (initialUri) { + visual.uri = initialUri; + } + return visual; } @@ -178,8 +182,8 @@ export class VisualService { ); } - async createVisualBanner(uri?: string): Promise { - return await this.createVisual( + public createVisualBanner(uri?: string): IVisual { + return this.createVisual( { name: 'banner', minWidth: 384, @@ -192,8 +196,8 @@ export class VisualService { ); } - async createVisualCard(uri?: string): Promise { - return await this.createVisual( + public createVisualCard(uri?: string): IVisual { + return this.createVisual( { name: 'card', minWidth: 307, @@ -206,8 +210,8 @@ export class VisualService { ); } - async createVisualBannerWide(uri?: string): Promise { - return await this.createVisual( + public createVisualBannerWide(uri?: string): IVisual { + return this.createVisual( { name: 'bannerWide', minWidth: 640, @@ -220,8 +224,8 @@ export class VisualService { ); } - async createVisualAvatar(): Promise { - return await this.createVisual({ + public createVisualAvatar(): IVisual { + return this.createVisual({ name: 'avatar', minWidth: avatarMinImageSize, maxWidth: avatarMaxImageSize, diff --git a/src/domain/common/whiteboard/whiteboard.service.ts b/src/domain/common/whiteboard/whiteboard.service.ts index 90b5d930bb..0add1d7733 100644 --- a/src/domain/common/whiteboard/whiteboard.service.ts +++ b/src/domain/common/whiteboard/whiteboard.service.ts @@ -73,16 +73,13 @@ export class WhiteboardService { ProfileType.WHITEBOARD, storageAggregator ); - await this.profileService.addVisualOnProfile( - whiteboard.profile, - VisualType.CARD - ); + this.profileService.addVisualOnProfile(whiteboard.profile, VisualType.CARD); await this.profileService.addTagsetOnProfile(whiteboard.profile, { name: TagsetReservedName.DEFAULT, tags: [], }); - return this.save(whiteboard); + return whiteboard; } async getWhiteboardOrFail( diff --git a/src/domain/communication/room/room.service.ts b/src/domain/communication/room/room.service.ts index d39dec08d3..5486a47011 100644 --- a/src/domain/communication/room/room.service.ts +++ b/src/domain/communication/room/room.service.ts @@ -44,7 +44,7 @@ export class RoomService { room.externalRoomID = await this.initializeCommunicationRoom(room); room.messagesCount = 0; room.vcInteractions = []; - return await this.roomRepository.save(room); + return room; } async getRoomOrFail( From d95e50b3969f2d1a5835521266f1f3a527cf7785 Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Wed, 24 Jul 2024 17:36:12 +0300 Subject: [PATCH 04/27] (almost) atomic profile creation --- .../common/location/location.service.ts | 5 ++- src/domain/common/profile/profile.service.ts | 34 ++++++------------- .../common/reference/reference.service.ts | 6 ++-- src/domain/common/tagset/tagset.service.ts | 7 ++-- .../storage-bucket/storage.bucket.service.ts | 14 ++++---- 5 files changed, 24 insertions(+), 42 deletions(-) diff --git a/src/domain/common/location/location.service.ts b/src/domain/common/location/location.service.ts index 25ed04a930..c01ffd826e 100644 --- a/src/domain/common/location/location.service.ts +++ b/src/domain/common/location/location.service.ts @@ -14,9 +14,8 @@ export class LocationService { private locationRepository: Repository ) {} - async createLocation(locationData?: CreateLocationInput): Promise { - const location = Location.create({ ...locationData }); - return await this.locationRepository.save(location); + public createLocation(locationData?: CreateLocationInput): ILocation { + return Location.create({ ...locationData }); } async removeLocation(location: ILocation): Promise { return await this.locationRepository.remove(location as Location); diff --git a/src/domain/common/profile/profile.service.ts b/src/domain/common/profile/profile.service.ts index 9a947e7f91..cc7dbdd6c5 100644 --- a/src/domain/common/profile/profile.service.ts +++ b/src/domain/common/profile/profile.service.ts @@ -59,41 +59,27 @@ export class ProfileService { type: profileType, }); profile.authorization = new AuthorizationPolicy(); + // the next statement fails if it's not saved profile.storageBucket = await this.storageBucketService.createStorageBucket( { storageAggregator: storageAggregator } ); profile.visuals = []; - profile.location = await this.locationService.createLocation( + profile.location = this.locationService.createLocation( profileData?.location ); - profile.references = []; - if (profileData?.referencesData) { - for (const referenceData of profileData.referencesData) { - const reference = - await this.referenceService.createReference(referenceData); - profile.references.push(reference); - } - } - await this.profileRepository.save(profile); - this.logger.verbose?.( - `Created new profile with id: ${profile.id}`, - LogContext.COMMUNITY + const newReferences = profileData?.referencesData?.map( + this.referenceService.createReference ); + profile.references = newReferences ?? []; - profile.tagsets = []; - if (profileData?.tagsets) { - for (const tagsetData of profileData?.tagsets) { - const tagset = await this.tagsetService.createTagsetWithName( - profile.tagsets, - tagsetData - ); - profile.tagsets.push(tagset); - } - } + const tagsetsFromInput = profileData?.tagsets?.map(tagsetData => + this.tagsetService.createTagsetWithName([], tagsetData) + ); + profile.tagsets = tagsetsFromInput ?? []; - return await this.save(profile); + return profile; } async updateProfile( diff --git a/src/domain/common/reference/reference.service.ts b/src/domain/common/reference/reference.service.ts index bbc7ae679f..4471647e24 100644 --- a/src/domain/common/reference/reference.service.ts +++ b/src/domain/common/reference/reference.service.ts @@ -21,16 +21,14 @@ export class ReferenceService { private referenceRepository: Repository ) {} - async createReference( - referenceInput: CreateReferenceInput - ): Promise { + public createReference(referenceInput: CreateReferenceInput): IReference { const reference = new Reference( referenceInput.name, referenceInput.uri || '', referenceInput.description ); reference.authorization = new AuthorizationPolicy(); - await this.referenceRepository.save(reference); + return reference; } diff --git a/src/domain/common/tagset/tagset.service.ts b/src/domain/common/tagset/tagset.service.ts index aa0603db4d..54e960da0b 100644 --- a/src/domain/common/tagset/tagset.service.ts +++ b/src/domain/common/tagset/tagset.service.ts @@ -1,3 +1,4 @@ +import { some } from 'lodash'; import { Inject, Injectable, LoggerService } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; @@ -233,10 +234,10 @@ export class TagsetService { return tagset; } - async createTagsetWithName( + public createTagsetWithName( existingTagsets: ITagset[], tagsetData: CreateTagsetInput - ): Promise { + ): ITagset { // Check if the group already exists, if so log a warning if (this.hasTagsetWithName(existingTagsets, tagsetData.name)) { throw new ValidationException( @@ -245,7 +246,7 @@ export class TagsetService { ); } - return await this.createTagset(tagsetData); + return Tagset.create({ ...tagsetData }); } async save(tagset: ITagset): Promise { diff --git a/src/domain/storage/storage-bucket/storage.bucket.service.ts b/src/domain/storage/storage-bucket/storage.bucket.service.ts index 8d9ae6efb2..47169b609f 100644 --- a/src/domain/storage/storage-bucket/storage.bucket.service.ts +++ b/src/domain/storage/storage-bucket/storage.bucket.service.ts @@ -51,7 +51,7 @@ export class StorageBucketService { private profileRepository: Repository ) {} - public async createStorageBucket( + public createStorageBucket( storageBucketData: CreateStorageBucketInput ): Promise { const storage: IStorageBucket = new StorageBucket(); @@ -63,7 +63,7 @@ export class StorageBucketService { storageBucketData?.maxFileSize || this.DEFAULT_MAX_ALLOWED_FILE_SIZE; storage.storageAggregator = storageBucketData.storageAggregator; - return await this.storageBucketRepository.save(storage); + return this.storageBucketRepository.save(storage); } async deleteStorageBucket(storageID: string): Promise { @@ -188,9 +188,8 @@ export class StorageBucketService { /* just consume */ } - const document = await this.documentService.createDocument( - createDocumentInput - ); + const document = + await this.documentService.createDocument(createDocumentInput); document.storageBucket = storage; this.logger.verbose?.( @@ -215,9 +214,8 @@ export class StorageBucketService { LogContext.DOCUMENT ); - const documentForReference = await this.documentService.getDocumentFromURL( - uri - ); + const documentForReference = + await this.documentService.getDocumentFromURL(uri); try { const newDocument = await this.uploadFileAsDocument( From 6550bda18ca832d7e7fe6b8a6d8329dd09833d27 Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Thu, 25 Jul 2024 16:31:45 +0300 Subject: [PATCH 05/27] atomic creation of callout --- .../callout.framing.service.ts | 2 +- .../collaboration/callout/callout.service.ts | 2 +- .../collaboration.resolver.mutations.ts | 5 +++- .../collaboration/collaboration.service.ts | 29 ++++++++++--------- 4 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/domain/collaboration/callout-framing/callout.framing.service.ts b/src/domain/collaboration/callout-framing/callout.framing.service.ts index 7356b825ba..ce5c92b3ba 100644 --- a/src/domain/collaboration/callout-framing/callout.framing.service.ts +++ b/src/domain/collaboration/callout-framing/callout.framing.service.ts @@ -85,7 +85,7 @@ export class CalloutFramingService { storageAggregator, userID ); - await this.profileService.addVisualOnProfile( + this.profileService.addVisualOnProfile( calloutFraming.whiteboard.profile, VisualType.BANNER ); diff --git a/src/domain/collaboration/callout/callout.service.ts b/src/domain/collaboration/callout/callout.service.ts index 67bec1728c..36015f800b 100644 --- a/src/domain/collaboration/callout/callout.service.ts +++ b/src/domain/collaboration/callout/callout.service.ts @@ -110,7 +110,7 @@ export class CalloutService { ); } - return this.calloutRepository.save(callout); + return callout; } private validateCreateCalloutData(calloutData: CreateCalloutInput) { diff --git a/src/domain/collaboration/collaboration/collaboration.resolver.mutations.ts b/src/domain/collaboration/collaboration/collaboration.resolver.mutations.ts index aee52df148..0e57f849a8 100644 --- a/src/domain/collaboration/collaboration/collaboration.resolver.mutations.ts +++ b/src/domain/collaboration/collaboration/collaboration.resolver.mutations.ts @@ -132,7 +132,6 @@ export class CollaborationResolverMutations { `create callout on collaboration: ${collaboration.id}` ); - // This also saves the callout let callout = await this.collaborationService.createCalloutOnCollaboration( calloutData, agentInfo.userID @@ -142,12 +141,16 @@ export class CollaborationResolverMutations { await this.namingService.getCommunityPolicyAndSettingsForCollaboration( collaboration.id ); + // callout needs to be saved to apply the authorization policy + await this.calloutService.save(callout); + callout = await this.calloutAuthorizationService.applyAuthorizationPolicy( callout, collaboration.authorization, communityPolicy, spaceSettings ); + // needs to save the authorization policy callout = await this.calloutService.save(callout); if (callout.visibility === CalloutVisibility.PUBLISHED) { diff --git a/src/domain/collaboration/collaboration/collaboration.service.ts b/src/domain/collaboration/collaboration/collaboration.service.ts index 09715122f0..b9627b2355 100644 --- a/src/domain/collaboration/collaboration/collaboration.service.ts +++ b/src/domain/collaboration/collaboration/collaboration.service.ts @@ -387,21 +387,22 @@ export class CollaborationService { await this.namingService.getReservedNameIDsInCollaboration( collaboration.id ); - if (calloutData.nameID && calloutData.nameID.length > 0) { - const nameIdAlreadyTaken = reservedNameIDs.includes(calloutData.nameID); - if (nameIdAlreadyTaken) - throw new ValidationException( - `Unable to create Callout: the provided nameID is already taken: ${calloutData.nameID}`, - LogContext.SPACES - ); - } else { - calloutData.nameID = - this.namingService.createNameIdAvoidingReservedNameIDs( - `${calloutData.framing.profile.displayName}`, - reservedNameIDs - ); + if ( + calloutData.nameID && + calloutData.nameID.length > 0 && + reservedNameIDs.includes(calloutData.nameID) + ) { + throw new ValidationException( + `Unable to create Callout: the provided nameID is already taken: ${calloutData.nameID}`, + LogContext.SPACES + ); } + calloutData.nameID = this.namingService.createNameIdAvoidingReservedNameIDs( + `${calloutData.framing.profile.displayName}`, + reservedNameIDs + ); + const tagsetTemplates = collaboration.tagsetTemplateSet.tagsetTemplates; const storageAggregator = await this.storageAggregatorResolverService.getStorageAggregatorForCollaboration( @@ -416,7 +417,7 @@ export class CollaborationService { // this has the effect of adding the callout to the collaboration callout.collaboration = collaboration; - return this.calloutService.save(callout); + return callout; } async getTimelineOrFail(collaborationID: string): Promise { From 19d14df6abf2cafc8ad6b4adbdc33975f3c615bd Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Fri, 26 Jul 2024 15:25:09 +0300 Subject: [PATCH 06/27] tagset creation fix --- src/domain/common/tagset/tagset.service.ts | 24 +++++++++------------- src/domain/community/user/user.service.ts | 2 +- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/domain/common/tagset/tagset.service.ts b/src/domain/common/tagset/tagset.service.ts index 54e960da0b..6c4e2c962a 100644 --- a/src/domain/common/tagset/tagset.service.ts +++ b/src/domain/common/tagset/tagset.service.ts @@ -1,4 +1,3 @@ -import { some } from 'lodash'; import { Inject, Injectable, LoggerService } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; @@ -7,11 +6,7 @@ import { Tagset } from './tagset.entity'; import { ITagset } from './tagset.interface'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { LogContext } from '@common/enums'; -import { - EntityNotFoundException, - RelationshipNotFoundException, - ValidationException, -} from '@common/exceptions'; +import { EntityNotFoundException, RelationshipNotFoundException, ValidationException } from '@common/exceptions'; import { CreateTagsetInput } from '@domain/common/tagset/dto/tagset.dto.create'; import { UpdateTagsetInput } from '@domain/common/tagset/dto/tagset.dto.update'; import { AuthorizationPolicy } from '@domain/common/authorization-policy'; @@ -30,13 +25,14 @@ export class TagsetService { @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} - async createTagset(tagsetData: CreateTagsetInput): Promise { - if (!tagsetData.type) tagsetData.type = TagsetType.FREEFORM; - const tagset: ITagset = Tagset.create({ ...tagsetData }); - tagset.authorization = new AuthorizationPolicy(); - if (!tagset.tags) tagset.tags = []; - tagset.tagsetTemplate = tagsetData.tagsetTemplate; - return await this.tagsetRepository.save(tagset); + public createTagset(tagsetData: CreateTagsetInput): ITagset { + return Tagset.create({ + ...tagsetData, + authorization: new AuthorizationPolicy(), + type: tagsetData.type ?? TagsetType.FREEFORM, + tags: tagsetData?.tags ?? [], + tagsetTemplate: tagsetData.tagsetTemplate, + }); } async getTagsetOrFail( @@ -246,7 +242,7 @@ export class TagsetService { ); } - return Tagset.create({ ...tagsetData }); + return this.createTagset(tagsetData); } async save(tagset: ITagset): Promise { diff --git a/src/domain/community/user/user.service.ts b/src/domain/community/user/user.service.ts index 095b15f798..000e380dc1 100644 --- a/src/domain/community/user/user.service.ts +++ b/src/domain/community/user/user.service.ts @@ -143,7 +143,7 @@ export class UserService { user.lastName ); } - await this.profileService.addVisualOnProfile( + this.profileService.addVisualOnProfile( user.profile, VisualType.AVATAR, avatarURL From 4475f67c37aff5f8310fffd93a804dcd751c974d Mon Sep 17 00:00:00 2001 From: hero101 Date: Tue, 30 Jul 2024 16:28:54 +0300 Subject: [PATCH 07/27] changed config service type --- src/app.module.ts | 13 +- .../innovation.hub.interceptor.ts | 11 +- src/config/winston.config.ts | 3 +- .../agent.info.cache.service.ts | 3 +- .../authentication/authentication.service.ts | 3 +- src/core/authentication/ory.api.strategy.ts | 3 +- src/core/authentication/ory.strategy.ts | 3 +- src/core/bootstrap/bootstrap.service.ts | 15 +- .../auth.reset.service.factory.ts | 3 +- .../matrix.adapter.service.factory.ts | 3 +- .../notifications.service.factory.ts | 3 +- .../subscription.factory.provider.ts | 6 +- .../microservices/subscription.factory.ts | 3 +- ...ngine.community.manager.service.factory.ts | 3 +- ...ntributor.engine.expert.service.factory.ts | 3 +- ...ributor.engine.guidance.service.factory.ts | 3 +- .../wallet-manager.service.factory.ts | 3 +- .../middleware/request.logger.middleware.ts | 3 +- .../middleware/session.extend.middleware.ts | 3 +- .../agent/agent/agent.resolver.fields.ts | 3 +- src/domain/agent/agent/agent.service.ts | 3 +- .../storage/document/document.service.ts | 3 +- src/main.ts | 4 +- .../configuration/config/config.service.ts | 3 +- .../communication.adapter.ts | 65 ++--- .../notification.payload.builder.ts | 28 +- .../adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts | 3 +- .../adapters/storage/ipfs/ipfs.service.ts | 3 +- .../local-storage/local.storage.adapter.ts | 3 +- .../chat-guidance/chat.guidance.service.ts | 3 +- .../api/search/v1/search.resolver.queries.ts | 3 +- .../v2/extract/search.extract.service.ts | 3 +- .../api/search/v2/ingest/get.index.pattern.ts | 5 +- .../search/v2/ingest/search.ingest.service.ts | 3 +- .../contribution.reporter.service.ts | 3 +- .../elasticsearch.client.factory.ts | 3 +- .../guidance.reporter.service.ts | 3 +- .../name-reporter/name.reporter.service.ts | 3 +- ...excalidraw.amqp.server.factory.provider.ts | 5 +- ...xcalidraw.redis.server.factory.provider.ts | 5 +- .../excalidraw-backend/excalidraw.server.ts | 3 +- .../utils/get.excalidraw.base.server.ts | 3 +- .../geo-location/geo.location.service.ts | 3 +- .../trust.registry.adapter.ts | 3 +- .../trust.registry.configuration.adapter.ts | 3 +- .../event-bus/event.bus.module.ts | 3 +- .../url-generator/url.generator.service.ts | 3 +- .../whiteboard.integration.service.ts | 3 +- src/types/alkemio.config.ts | 258 ++++++++++++++++++ src/types/index.ts | 1 + 50 files changed, 416 insertions(+), 114 deletions(-) create mode 100644 src/types/alkemio.config.ts diff --git a/src/app.module.ts b/src/app.module.ts index 357b735ad6..847ea3f489 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -32,6 +32,7 @@ import { print } from 'graphql/language/printer'; import { WinstonModule } from 'nest-winston'; import { join } from 'path'; import { + AlkemioConfig, ConnectionContext, SubscriptionsTransportWsWebsocket, WebsocketContext, @@ -90,7 +91,9 @@ import { LookupByNameModule } from '@services/api/lookup-by-name'; CacheModule.registerAsync({ isGlobal: true, imports: [ConfigModule], - useFactory: async (configService: ConfigService) => ({ + useFactory: async ( + configService: ConfigService + ) => ({ store: redisStore, host: configService.get(ConfigurationTypes.STORAGE)?.redis?.host, port: configService.get(ConfigurationTypes.STORAGE)?.redis?.port, @@ -106,7 +109,9 @@ import { LookupByNameModule } from '@services/api/lookup-by-name'; name: 'default', imports: [ConfigModule], inject: [ConfigService], - useFactory: async (configService: ConfigService) => ({ + useFactory: async ( + configService: ConfigService + ) => ({ type: 'mysql', insecureAuth: true, synchronize: false, @@ -133,7 +138,9 @@ import { LookupByNameModule } from '@services/api/lookup-by-name'; driver: ApolloDriver, imports: [ConfigModule], inject: [ConfigService], - useFactory: async (configService: ConfigService) => ({ + useFactory: async ( + configService: ConfigService + ) => ({ cors: false, // this is to avoid a duplicate cors origin header being created when behind the oathkeeper reverse proxy uploads: false, autoSchemaFile: true, diff --git a/src/common/interceptors/innovation.hub.interceptor.ts b/src/common/interceptors/innovation.hub.interceptor.ts index 9255df17c7..fe7a647ab6 100644 --- a/src/common/interceptors/innovation.hub.interceptor.ts +++ b/src/common/interceptors/innovation.hub.interceptor.ts @@ -9,9 +9,10 @@ import { ConfigService } from '@nestjs/config'; import { GqlExecutionContext } from '@nestjs/graphql'; import { INNOVATION_HUB_INJECT_TOKEN } from '@common/constants'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { InnovationHubService } from '@domain/innovation-hub'; import { DOMAIN_PATTERN, SUBDOMAIN_PATTERN } from '@core/validation'; +import { AlkemioConfig } from '@src/types'; const SUBDOMAIN_GROUP = 'subdomain'; @@ -37,13 +38,13 @@ export class InnovationHubInterceptor implements NestInterceptor { constructor( private readonly innovationHubService: InnovationHubService, - private readonly configService: ConfigService, + private readonly configService: ConfigService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { - this.innovationHubHeader = this.configService.get( - ConfigurationTypes.INNOVATION_HUB - )?.header; + this.innovationHubHeader = this.configService.get('innovation_hub.header', { + infer: true, + }); } async intercept(context: ExecutionContext, next: CallHandler) { diff --git a/src/config/winston.config.ts b/src/config/winston.config.ts index 20b2de5a2f..e2fcc43813 100644 --- a/src/config/winston.config.ts +++ b/src/config/winston.config.ts @@ -5,6 +5,7 @@ import { ConfigService } from '@nestjs/config'; import { ConfigurationTypes } from '@common/enums'; import { FileTransportOptions } from 'winston/lib/winston/transports'; import * as logform from 'logform'; +import { AlkemioConfig } from '@src/types'; const LOG_LABEL = 'alkemio-server'; @@ -24,7 +25,7 @@ const consoleLoggingProdFormat: logform.Format[] = [ @Injectable() export class WinstonConfigService { - constructor(private configService: ConfigService) {} + constructor(private configService: ConfigService) {} async createWinstonModuleOptions() { const consoleEnabled: boolean = this.configService.get( diff --git a/src/core/authentication.agent.info/agent.info.cache.service.ts b/src/core/authentication.agent.info/agent.info.cache.service.ts index 9c06ab3fb8..8e3d298c0c 100644 --- a/src/core/authentication.agent.info/agent.info.cache.service.ts +++ b/src/core/authentication.agent.info/agent.info.cache.service.ts @@ -11,6 +11,7 @@ import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; // import Redlock, { RedlockAbortSignal } from 'redlock'; import { EntityManager } from 'typeorm'; import { IAgent, ICredential } from '../../domain/agent'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class AgentInfoCacheService { private readonly cache_ttl: number; @@ -22,7 +23,7 @@ export class AgentInfoCacheService { // private readonly redisLockService: Redlock, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService, - private configService: ConfigService, + private configService: ConfigService, @InjectEntityManager('default') private entityManager: EntityManager ) { diff --git a/src/core/authentication/authentication.service.ts b/src/core/authentication/authentication.service.ts index 9f8e68b75a..45859a4569 100644 --- a/src/core/authentication/authentication.service.ts +++ b/src/core/authentication/authentication.service.ts @@ -19,6 +19,7 @@ import { SessionExtendException } from '@common/exceptions/auth'; import { AgentInfoCacheService } from '@core/authentication.agent.info/agent.info.cache.service'; import { getSession } from '@common/utils'; import ConfigUtils from '@config/config.utils'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class AuthenticationService { @@ -31,7 +32,7 @@ export class AuthenticationService { constructor( private agentCacheService: AgentInfoCacheService, - private configService: ConfigService, + private configService: ConfigService, private userService: UserService, private agentService: AgentService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService diff --git a/src/core/authentication/ory.api.strategy.ts b/src/core/authentication/ory.api.strategy.ts index 92747a74ac..bdd5d36c65 100644 --- a/src/core/authentication/ory.api.strategy.ts +++ b/src/core/authentication/ory.api.strategy.ts @@ -10,6 +10,7 @@ import { AuthenticationService } from './authentication.service'; import { OryDefaultIdentitySchema } from './ory.default.identity.schema'; import { verifyIdentityIfOidcAuth } from './verify.identity.if.oidc.auth'; import { IncomingMessage } from 'http'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class OryApiStrategy extends PassportStrategy( @@ -18,7 +19,7 @@ export class OryApiStrategy extends PassportStrategy( ) { private readonly kratosClient: FrontendApi; constructor( - private readonly configService: ConfigService, + private readonly configService: ConfigService, private readonly authService: AuthenticationService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { diff --git a/src/core/authentication/ory.strategy.ts b/src/core/authentication/ory.strategy.ts index cbf86f9df8..a04c33cf1b 100644 --- a/src/core/authentication/ory.strategy.ts +++ b/src/core/authentication/ory.strategy.ts @@ -15,11 +15,12 @@ import { KratosPayload } from './kratos.payload'; import { verifyIdentityIfOidcAuth } from './verify.identity.if.oidc.auth'; import { AgentInfo } from '../authentication.agent.info/agent.info'; import { SessionExpiredException } from '@common/exceptions/session.expired.exception'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class OryStrategy extends PassportStrategy(Strategy, 'oathkeeper-jwt') { constructor( - private readonly configService: ConfigService, + private readonly configService: ConfigService, private readonly authService: AuthenticationService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { diff --git a/src/core/bootstrap/bootstrap.service.ts b/src/core/bootstrap/bootstrap.service.ts index e0358072ad..e8636bf09d 100644 --- a/src/core/bootstrap/bootstrap.service.ts +++ b/src/core/bootstrap/bootstrap.service.ts @@ -33,6 +33,7 @@ import { SearchIngestService } from '@services/api/search/v2/ingest/search.inges import { CreateAccountInput } from '@domain/space/account/dto/account.dto.create'; import { SpaceLevel } from '@common/enums/space.level'; import { CreateSpaceOnAccountInput } from '@domain/space/account/dto/account.dto.create.space'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class BootstrapService { @@ -44,7 +45,7 @@ export class BootstrapService { private userAuthorizationService: UserAuthorizationService, private accountAuthorizationService: AccountAuthorizationService, private adminAuthorizationService: AdminAuthorizationService, - private configService: ConfigService, + private configService: ConfigService, private organizationService: OrganizationService, private platformService: PlatformService, private organizationAuthorizationService: OrganizationAuthorizationService, @@ -202,9 +203,8 @@ export class BootstrapService { }); } user = await this.userAuthorizationService.grantCredentials(user); - user = await this.userAuthorizationService.applyAuthorizationPolicy( - user - ); + user = + await this.userAuthorizationService.applyAuthorizationPolicy(user); } } } catch (error: any) { @@ -303,9 +303,10 @@ export class BootstrapService { account, createSpaceAccountInput ); - account = await this.accountAuthorizationService.applyAuthorizationPolicy( - account - ); + account = + await this.accountAuthorizationService.applyAuthorizationPolicy( + account + ); return await this.accountService.save(account); } } diff --git a/src/core/microservices/auth.reset.service.factory.ts b/src/core/microservices/auth.reset.service.factory.ts index 4893bf0cc9..9474c63101 100644 --- a/src/core/microservices/auth.reset.service.factory.ts +++ b/src/core/microservices/auth.reset.service.factory.ts @@ -3,10 +3,11 @@ import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ClientProxyFactory, Transport } from '@nestjs/microservices'; +import { AlkemioConfig } from '@src/types'; export async function authResetServiceFactory( logger: LoggerService, - configService: ConfigService + configService: ConfigService ): Promise { const rabbitMqOptions = configService.get( ConfigurationTypes.MICROSERVICES diff --git a/src/core/microservices/matrix.adapter.service.factory.ts b/src/core/microservices/matrix.adapter.service.factory.ts index 62f1fca0c1..e031bf3aae 100644 --- a/src/core/microservices/matrix.adapter.service.factory.ts +++ b/src/core/microservices/matrix.adapter.service.factory.ts @@ -3,10 +3,11 @@ import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ClientProxyFactory, Transport } from '@nestjs/microservices'; +import { AlkemioConfig } from '@src/types'; export async function matrixAdapterServiceFactory( logger: LoggerService, - configService: ConfigService + configService: ConfigService ): Promise { const rabbitMqOptions = configService.get( ConfigurationTypes.MICROSERVICES diff --git a/src/core/microservices/notifications.service.factory.ts b/src/core/microservices/notifications.service.factory.ts index 842f688cf2..98fd46dd9a 100644 --- a/src/core/microservices/notifications.service.factory.ts +++ b/src/core/microservices/notifications.service.factory.ts @@ -3,10 +3,11 @@ import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ClientProxyFactory, Transport } from '@nestjs/microservices'; +import { AlkemioConfig } from '@src/types'; export async function notificationsServiceFactory( logger: LoggerService, - configService: ConfigService + configService: ConfigService ): Promise { const rabbitMqOptions = configService.get( ConfigurationTypes.MICROSERVICES diff --git a/src/core/microservices/subscription.factory.provider.ts b/src/core/microservices/subscription.factory.provider.ts index f51025ac9d..9b2b0b7854 100644 --- a/src/core/microservices/subscription.factory.provider.ts +++ b/src/core/microservices/subscription.factory.provider.ts @@ -4,6 +4,7 @@ import { PubSubEngine } from 'graphql-subscriptions'; import { ConfigService } from '@nestjs/config'; import { subscriptionFactory } from '@core/microservices/subscription.factory'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; +import { AlkemioConfig } from '@src/types'; /*** * Creates a factory provider for a subscription @@ -21,7 +22,10 @@ export const subscriptionFactoryProvider = ( trackingID = '' ): FactoryProvider> => ({ provide, - useFactory: (logger: LoggerService, configService: ConfigService) => + useFactory: ( + logger: LoggerService, + configService: ConfigService + ) => subscriptionFactory( logger, configService, diff --git a/src/core/microservices/subscription.factory.ts b/src/core/microservices/subscription.factory.ts index 037dfd03e4..7cdfd6d5c3 100644 --- a/src/core/microservices/subscription.factory.ts +++ b/src/core/microservices/subscription.factory.ts @@ -4,10 +4,11 @@ import { PubSubEngine } from 'graphql-subscriptions'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ConfigurationTypes, LogContext } from '@common/enums'; +import { AlkemioConfig } from '@src/types'; export async function subscriptionFactory( logger: LoggerService, - configService: ConfigService, + configService: ConfigService, exchangeName: string, queueName: string ): Promise { diff --git a/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts b/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts index d0e9fed392..7ef853bc06 100644 --- a/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts +++ b/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts @@ -3,10 +3,11 @@ import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ClientProxyFactory, Transport } from '@nestjs/microservices'; +import { AlkemioConfig } from '@src/types'; export async function virtualContributorEngineCommunityManagerServiceFactory( logger: LoggerService, - configService: ConfigService + configService: ConfigService ): Promise { const rabbitMqOptions = configService.get( ConfigurationTypes.MICROSERVICES diff --git a/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts b/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts index d0131b763b..64be82f8ea 100644 --- a/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts +++ b/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts @@ -3,10 +3,11 @@ import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ClientProxyFactory, Transport } from '@nestjs/microservices'; +import { AlkemioConfig } from '@src/types'; export async function virtualContributorEngineExpertServiceFactory( logger: LoggerService, - configService: ConfigService + configService: ConfigService ): Promise { const rabbitMqOptions = configService.get( ConfigurationTypes.MICROSERVICES diff --git a/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts b/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts index 8dcb66b449..313f618767 100644 --- a/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts +++ b/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts @@ -3,10 +3,11 @@ import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ClientProxyFactory, Transport } from '@nestjs/microservices'; +import { AlkemioConfig } from '@src/types'; export async function virtualContributorEngineGuidanceServiceFactory( logger: LoggerService, - configService: ConfigService + configService: ConfigService ): Promise { const rabbitMqOptions = configService.get( ConfigurationTypes.MICROSERVICES diff --git a/src/core/microservices/wallet-manager.service.factory.ts b/src/core/microservices/wallet-manager.service.factory.ts index 6b0a6e3314..99a31539c6 100644 --- a/src/core/microservices/wallet-manager.service.factory.ts +++ b/src/core/microservices/wallet-manager.service.factory.ts @@ -3,10 +3,11 @@ import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { ClientProxyFactory, Transport } from '@nestjs/microservices'; +import { AlkemioConfig } from '@src/types'; export async function walletManagerServiceFactory( logger: LoggerService, - configService: ConfigService + configService: ConfigService ): Promise { const rabbitMqOptions = configService.get( ConfigurationTypes.MICROSERVICES diff --git a/src/core/middleware/request.logger.middleware.ts b/src/core/middleware/request.logger.middleware.ts index 73bab212e1..bf24d7a02a 100644 --- a/src/core/middleware/request.logger.middleware.ts +++ b/src/core/middleware/request.logger.middleware.ts @@ -8,6 +8,7 @@ import { Request, Response, NextFunction } from 'express'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { ConfigService } from '@nestjs/config'; import { ConfigurationTypes, LogContext } from '@common/enums'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class RequestLoggerMiddleware implements NestMiddleware { @@ -15,7 +16,7 @@ export class RequestLoggerMiddleware implements NestMiddleware { private requestHeadersLogging = false; private responseHeadersLogging = false; constructor( - private readonly configService: ConfigService, + private readonly configService: ConfigService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { const reqLoggingConfig = this.configService.get( diff --git a/src/core/middleware/session.extend.middleware.ts b/src/core/middleware/session.extend.middleware.ts index 65f63e7044..36f1f79afd 100644 --- a/src/core/middleware/session.extend.middleware.ts +++ b/src/core/middleware/session.extend.middleware.ts @@ -11,6 +11,7 @@ import { AuthenticationService } from '@core/authentication/authentication.servi import { ConfigurationTypes, LogContext } from '@src/common/enums'; import { getSessionFromJwt } from '@common/utils'; import { Configuration, FrontendApi, Session } from '@ory/kratos-client'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class SessionExtendMiddleware implements NestMiddleware { @@ -21,7 +22,7 @@ export class SessionExtendMiddleware implements NestMiddleware { @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService, private readonly authService: AuthenticationService, - private readonly configService: ConfigService + private readonly configService: ConfigService ) { this.SESSION_COOKIE_NAME = this.configService.get( ConfigurationTypes.IDENTITY diff --git a/src/domain/agent/agent/agent.resolver.fields.ts b/src/domain/agent/agent/agent.resolver.fields.ts index 0b9b7c0033..48354a1dda 100644 --- a/src/domain/agent/agent/agent.resolver.fields.ts +++ b/src/domain/agent/agent/agent.resolver.fields.ts @@ -13,11 +13,12 @@ import { GraphqlGuard } from '@core/authorization'; import { ConfigService } from '@nestjs/config'; import { NotEnabledException } from '@common/exceptions/not.enabled.exception'; import { IVerifiedCredential } from '../verified-credential/verified.credential.interface'; +import { AlkemioConfig } from '@src/types'; @Resolver(() => IAgent) export class AgentResolverFields { constructor( - private configService: ConfigService, + private configService: ConfigService, private agentService: AgentService ) {} diff --git a/src/domain/agent/agent/agent.service.ts b/src/domain/agent/agent/agent.service.ts index 669bef2ba0..c6b4c298e3 100644 --- a/src/domain/agent/agent/agent.service.ts +++ b/src/domain/agent/agent/agent.service.ts @@ -45,6 +45,7 @@ import { SsiSovrhdRegisterCallbackCredential } from '@services/adapters/ssi-sovr import { getRandomId } from '@src/common/utils'; import { AgentInfoCacheService } from '../../../core/authentication.agent.info/agent.info.cache.service'; import { GrantCredentialToAgentInput } from './dto/agent.dto.credential.grant'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class AgentService { @@ -53,7 +54,7 @@ export class AgentService { constructor( private agentInfoCacheService: AgentInfoCacheService, private authorizationPolicyService: AuthorizationPolicyService, - private configService: ConfigService, + private configService: ConfigService, private credentialService: CredentialService, @InjectRepository(Agent) private agentRepository: Repository, diff --git a/src/domain/storage/document/document.service.ts b/src/domain/storage/document/document.service.ts index a2e5c30df3..561d7ae2d8 100644 --- a/src/domain/storage/document/document.service.ts +++ b/src/domain/storage/document/document.service.ts @@ -19,11 +19,12 @@ import { TagsetReservedName } from '@common/enums/tagset.reserved.name'; import { STORAGE_SERVICE } from '@common/constants'; import { DocumentDeleteFailedException } from '@common/exceptions/document/document.delete.failed.exception'; import { DocumentSaveFailedException } from '@common/exceptions/document/document.save.failed.exception'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class DocumentService { constructor( - private configService: ConfigService, + private configService: ConfigService, private authorizationPolicyService: AuthorizationPolicyService, private tagsetService: TagsetService, @Inject(STORAGE_SERVICE) diff --git a/src/main.ts b/src/main.ts index 847e47149e..b0666dfc8a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -13,6 +13,7 @@ import { json } from 'body-parser'; import cookieParser from 'cookie-parser'; import { MicroserviceOptions, Transport } from '@nestjs/microservices'; import { INestApplication } from '@nestjs/common'; +import { AlkemioConfig } from '@src/types'; const bootstrap = async () => { const app = await NestFactory.create(AppModule, { @@ -24,7 +25,8 @@ const bootstrap = async () => { */ logger: process.env.NODE_ENV === 'production' ? false : undefined, }); - const configService: ConfigService = app.get(ConfigService); + const configService: ConfigService = + app.get(ConfigService); const logger = app.get(WINSTON_MODULE_NEST_PROVIDER); const bootstrapService: BootstrapService = app.get(BootstrapService); diff --git a/src/platform/configuration/config/config.service.ts b/src/platform/configuration/config/config.service.ts index b091e8f845..5af6f16a47 100644 --- a/src/platform/configuration/config/config.service.ts +++ b/src/platform/configuration/config/config.service.ts @@ -5,10 +5,11 @@ import { IAuthenticationProviderConfig } from './authentication/providers/authen import { ConfigurationTypes } from '@common/enums'; import { IOryConfig } from './authentication/providers/ory/ory.config.interface'; import { PlatformFeatureFlagName } from '@common/enums/platform.feature.flag.name'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class KonfigService { - constructor(private configService: ConfigService) {} + constructor(private configService: ConfigService) {} async getConfig(): Promise { const domain = new URL( diff --git a/src/services/adapters/communication-adapter/communication.adapter.ts b/src/services/adapters/communication-adapter/communication.adapter.ts index 4d00f74a72..6377fade6f 100644 --- a/src/services/adapters/communication-adapter/communication.adapter.ts +++ b/src/services/adapters/communication-adapter/communication.adapter.ts @@ -65,6 +65,7 @@ import { CommunicationRemoveRectionToMessageInput } from './dto/communication.dt import { CommunicationRoomResult } from '@services/adapters/communication-adapter/dto/communication.dto.room.result'; import { IMessageReaction } from '@domain/communication/message.reaction/message.reaction.interface'; import { RoomResult } from '@alkemio/matrix-adapter-lib/dist/types/room'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class CommunicationAdapter { @@ -75,7 +76,7 @@ export class CommunicationAdapter { constructor( @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService, - private configService: ConfigService, + private configService: ConfigService, @Inject(MATRIX_ADAPTER_SERVICE) private matrixAdapterClient: ClientProxy ) { const communications = this.configService.get( @@ -104,9 +105,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); const message = responseData.message; @@ -153,9 +153,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); const message = responseData.message; @@ -278,9 +277,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); return this.convertRoomDetailsResponseToCommunicationRoomResult( responseData @@ -443,9 +441,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); return responseData.userID; } catch (err: any) { @@ -478,9 +475,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); this.logger.verbose?.( `Created community room:'${responseData.roomID}'`, @@ -517,9 +513,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); return responseData.success; } catch (err: any) { @@ -552,9 +547,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); return responseData.rooms.map(room => { return { @@ -600,9 +594,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); return responseData.rooms.map(room => { return { @@ -742,9 +735,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); return responseData.success; } catch (err: any) { @@ -774,9 +766,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); this.logger.verbose?.( `[Membership] Removed members from room: ${matrixRoomID}`, @@ -811,9 +802,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); userIDs = responseData.userIDs; } catch (err: any) { @@ -847,9 +837,8 @@ export class CommunicationAdapter { ); try { - const responseData = await firstValueFrom( - response - ); + const responseData = + await firstValueFrom(response); this.logResponsePayload(eventType, responseData, eventID); return this.convertRoomDetailsResponseToCommunicationRoomResult( responseData @@ -902,7 +891,7 @@ export class CommunicationAdapter { private makeRetryableAndPromisify< T extends BaseMatrixAdapterEventResponsePayload, - TReturnType + TReturnType, >( input$: Observable, resultSelector: (result: T) => TReturnType, diff --git a/src/services/adapters/notification-adapter/notification.payload.builder.ts b/src/services/adapters/notification-adapter/notification.payload.builder.ts index 15218d6570..6434938558 100644 --- a/src/services/adapters/notification-adapter/notification.payload.builder.ts +++ b/src/services/adapters/notification-adapter/notification.payload.builder.ts @@ -54,6 +54,7 @@ import { IDiscussion } from '@platform/forum-discussion/discussion.interface'; import { ContributorLookupService } from '@services/infrastructure/contributor-lookup/contributor.lookup.service'; import { IContributor } from '@domain/community/contributor/contributor.interface'; import { IAccount } from '@domain/space/account/account.interface'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class NotificationPayloadBuilder { @@ -66,7 +67,7 @@ export class NotificationPayloadBuilder { private communityRepository: Repository, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService, - private configService: ConfigService, + private configService: ConfigService, private contributionResolverService: ContributionResolverService, private urlGeneratorService: UrlGeneratorService ) {} @@ -80,9 +81,8 @@ export class NotificationPayloadBuilder { community, applicationCreatorID ); - const applicantPayload = await this.getContributorPayloadOrFail( - applicantID - ); + const applicantPayload = + await this.getContributorPayloadOrFail(applicantID); const payload: CommunityApplicationCreatedEventPayload = { applicant: applicantPayload, ...spacePayload, @@ -101,9 +101,8 @@ export class NotificationPayloadBuilder { community, invitationCreatorID ); - const inviteePayload = await this.getContributorPayloadOrFail( - invitedUserID - ); + const inviteePayload = + await this.getContributorPayloadOrFail(invitedUserID); const payload: CommunityInvitationCreatedEventPayload = { invitee: inviteePayload, welcomeMessage, @@ -569,9 +568,8 @@ export class NotificationPayloadBuilder { const contributorType = this.contributorLookupService.getContributorType(contributor); - const userURL = await this.urlGeneratorService.createUrlForContributor( - contributor - ); + const userURL = + await this.urlGeneratorService.createUrlForContributor(contributor); const result: ContributorPayload = { id: contributor.id, nameID: contributor.nameID, @@ -590,9 +588,8 @@ export class NotificationPayloadBuilder { organizationID: string ): Promise { const basePayload = this.buildBaseEventPayload(senderID); - const orgContribtor = await this.getContributorPayloadOrFail( - organizationID - ); + const orgContribtor = + await this.getContributorPayloadOrFail(organizationID); const payload: CommunicationOrganizationMessageEventPayload = { message, organization: orgContribtor, @@ -625,9 +622,8 @@ export class NotificationPayloadBuilder { originEntityDisplayName: string, commentType: RoomType ): Promise { - const userContributor = await this.getContributorPayloadOrFail( - mentionedUserNameID - ); + const userContributor = + await this.getContributorPayloadOrFail(mentionedUserNameID); const commentOriginUrl = await this.buildCommentOriginUrl( commentType, diff --git a/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts b/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts index 9c7838c4b2..30c9ba70da 100644 --- a/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts +++ b/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts @@ -12,6 +12,7 @@ import { SsiSovrhdRegisterCallbackCredential } from './dto/ssi.sovrhd.dto.regist import { SsiSovrhdRegisterResponse } from './dto/ssi.sovrhd.dto.register.response'; import { SsiSovrhdRequest } from './dto/ssi.sovrhd.dto.request'; import { SsiSovrhdRequestResponse } from './dto/ssi.sovrhd.dto.request.response'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class SsiSovrhdAdapter { @@ -27,7 +28,7 @@ export class SsiSovrhdAdapter { constructor( @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService, - private configService: ConfigService, + private configService: ConfigService, private httpService: HttpService ) { const sovrhdConfig = this.configService.get(ConfigurationTypes.SSI)?.issuers diff --git a/src/services/adapters/storage/ipfs/ipfs.service.ts b/src/services/adapters/storage/ipfs/ipfs.service.ts index a5448ec39b..eef093771c 100644 --- a/src/services/adapters/storage/ipfs/ipfs.service.ts +++ b/src/services/adapters/storage/ipfs/ipfs.service.ts @@ -9,6 +9,7 @@ import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { CID, create, IPFSHTTPClient } from 'ipfs-http-client'; import { IpfsDeleteFailedException } from '@common/exceptions/ipfs/ipfs.delete.exception'; import { IpfsGCFailedException } from '@common/exceptions/ipfs/ipfs.gc.exception'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class IpfsService { @@ -16,7 +17,7 @@ export class IpfsService { private readonly ipfsClientEndpoint; constructor( - private configService: ConfigService, + private configService: ConfigService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { diff --git a/src/services/adapters/storage/local-storage/local.storage.adapter.ts b/src/services/adapters/storage/local-storage/local.storage.adapter.ts index 9bfcb8de90..f4560fcb16 100644 --- a/src/services/adapters/storage/local-storage/local.storage.adapter.ts +++ b/src/services/adapters/storage/local-storage/local.storage.adapter.ts @@ -12,6 +12,7 @@ import { } from '@common/exceptions/storage'; import { StorageService } from '../storage.service.interface'; import { StorageServiceType } from '../storage.service.type'; +import { AlkemioConfig } from '@src/types'; const writeFileAsync = promisify(writeFile); const readFileAsync = promisify(readFile); @@ -21,7 +22,7 @@ const unlinkAsync = promisify(unlink); export class LocalStorageAdapter implements StorageService { private readonly storagePath: string; - constructor(private configService: ConfigService) { + constructor(private configService: ConfigService) { const pathFromConfig = this.configService.get(ConfigurationTypes.STORAGE) ?.local_storage?.path; this.storagePath = pathResolve(pathFromConfig); diff --git a/src/services/api/chat-guidance/chat.guidance.service.ts b/src/services/api/chat-guidance/chat.guidance.service.ts index 21a6f0c147..5345b4361d 100644 --- a/src/services/api/chat-guidance/chat.guidance.service.ts +++ b/src/services/api/chat-guidance/chat.guidance.service.ts @@ -6,11 +6,12 @@ import { ConfigService } from '@nestjs/config'; import { GuidanceEngineAdapter } from '@services/adapters/chat-guidance-adapter/guidance.engine.adapter'; import { ChatGuidanceInput } from './dto/chat.guidance.dto.input'; import { IMessageAnswerToQuestion } from '@domain/communication/message.answer.to.question/message.answer.to.question.interface'; +import { AlkemioConfig } from '@src/types'; export class ChatGuidanceService { constructor( private guidanceEngineAdapter: GuidanceEngineAdapter, - private configService: ConfigService, + private configService: ConfigService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} diff --git a/src/services/api/search/v1/search.resolver.queries.ts b/src/services/api/search/v1/search.resolver.queries.ts index 3b2cb72046..f2144ad0d0 100644 --- a/src/services/api/search/v1/search.resolver.queries.ts +++ b/src/services/api/search/v1/search.resolver.queries.ts @@ -9,11 +9,12 @@ import { SearchService } from './search.service'; import { Search2Service } from '@services/api/search/v2/search2.service'; import { ConfigService } from '@nestjs/config'; import { ConfigurationTypes } from '@common/enums'; +import { AlkemioConfig } from '@src/types'; @Resolver() export class SearchResolverQueries { private readonly useNewSearch: boolean; constructor( - private configService: ConfigService, + private configService: ConfigService, private searchService: SearchService, private search2Service: Search2Service ) { diff --git a/src/services/api/search/v2/extract/search.extract.service.ts b/src/services/api/search/v2/extract/search.extract.service.ts index ecd61c5dc6..0b907ee639 100644 --- a/src/services/api/search/v2/extract/search.extract.service.ts +++ b/src/services/api/search/v2/extract/search.extract.service.ts @@ -16,6 +16,7 @@ import { validateSearchTerms, validateSearchParameters } from '../../util'; import { functionScoreFunctions } from './function.score.functions'; import { buildSearchQuery } from './build.search.query'; import { SearchEntityTypes } from '../../search.entity.types'; +import { AlkemioConfig } from '@src/types'; type SearchEntityTypesPublic = | SearchEntityTypes.SPACE @@ -54,7 +55,7 @@ export class SearchExtractService { @Inject(ELASTICSEARCH_CLIENT_PROVIDER) private client: ElasticClient | undefined, @Inject(WINSTON_MODULE_NEST_PROVIDER) private logger: LoggerService, - private configService: ConfigService + private configService: ConfigService ) { this.indexPattern = this.configService.get(ConfigurationTypes.SEARCH)?.index_pattern ?? diff --git a/src/services/api/search/v2/ingest/get.index.pattern.ts b/src/services/api/search/v2/ingest/get.index.pattern.ts index aaf8f3f7f6..b119205431 100644 --- a/src/services/api/search/v2/ingest/get.index.pattern.ts +++ b/src/services/api/search/v2/ingest/get.index.pattern.ts @@ -1,9 +1,12 @@ import { ConfigService } from '@nestjs/config'; import { ConfigurationTypes } from '@common/enums'; +import { AlkemioConfig } from '@src/types'; const DEFAULT_INDEX_PATTERN = 'alkemio-data-'; -export const getIndexPattern = (configService: ConfigService) => { +export const getIndexPattern = ( + configService: ConfigService +) => { const pattern = configService.get(ConfigurationTypes.SEARCH)?.index_pattern ?? DEFAULT_INDEX_PATTERN; diff --git a/src/services/api/search/v2/ingest/search.ingest.service.ts b/src/services/api/search/v2/ingest/search.ingest.service.ts index 342788c0f6..2d13e9b9a9 100644 --- a/src/services/api/search/v2/ingest/search.ingest.service.ts +++ b/src/services/api/search/v2/ingest/search.ingest.service.ts @@ -22,6 +22,7 @@ import { SearchEntityTypes } from '../../search.entity.types'; import { ExcalidrawContent, isExcalidrawTextElement } from '@common/interfaces'; import { TaskService } from '@services/task'; import { Task } from '@services/task/task.interface'; +import { AlkemioConfig } from '@src/types'; const profileRelationOptions = { location: true, @@ -101,7 +102,7 @@ export class SearchIngestService { private elasticClient: ElasticClient | undefined, @InjectEntityManager() private entityManager: EntityManager, @Inject(WINSTON_MODULE_NEST_PROVIDER) private logger: LoggerService, - private configService: ConfigService, + private configService: ConfigService, private taskService: TaskService ) { this.indexPattern = getIndexPattern(this.configService); diff --git a/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts b/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts index c7c63e6f85..0baf4a5bbf 100644 --- a/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts +++ b/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts @@ -13,6 +13,7 @@ import { } from '../types'; import { BaseContribution } from '../events'; import { ELASTICSEARCH_CLIENT_PROVIDER } from '@constants/index'; +import { AlkemioConfig } from '@src/types'; const isFromAlkemioTeam = (email: string) => /.*@alkem\.io/.test(email); @@ -24,7 +25,7 @@ export class ContributionReporterService { constructor( @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService, - private readonly configService: ConfigService, + private readonly configService: ConfigService, @Inject(ELASTICSEARCH_CLIENT_PROVIDER) private readonly client: ElasticClient | undefined ) { diff --git a/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts b/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts index 407837d978..c8107e2c7e 100644 --- a/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts +++ b/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts @@ -3,10 +3,11 @@ import { ConfigService } from '@nestjs/config'; import { Client } from '@elastic/elasticsearch'; import { ConfigurationTypes } from '@common/enums'; import fs from 'fs'; +import { AlkemioConfig } from '@src/types'; export const elasticSearchClientFactory = async ( logger: LoggerService, - configService: ConfigService + configService: ConfigService ): Promise => { const elasticsearch = configService.get( ConfigurationTypes.INTEGRATIONS diff --git a/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts b/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts index ecea74aac2..5c68928a86 100644 --- a/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts +++ b/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts @@ -11,6 +11,7 @@ import { GuidanceUsage } from './guidance.usage'; import { GuidanceUsageDocument } from './guidance.usage.document'; import { UserService } from '@domain/community/user/user.service'; import { GuidanceEngineQueryResponse } from '@services/adapters/chat-guidance-adapter/dto/guidance.engine.dto.question.response'; +import { AlkemioConfig } from '@src/types'; const isFromAlkemioTeam = (email: string) => /.*@alkem\.io/.test(email); @@ -23,7 +24,7 @@ export class GuidanceReporterService { @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService, private readonly userService: UserService, - private readonly configService: ConfigService, + private readonly configService: ConfigService, @Inject(ELASTICSEARCH_CLIENT_PROVIDER) private readonly client: ElasticClient | undefined ) { diff --git a/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts b/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts index 4dd908f6d2..a64a921442 100644 --- a/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts +++ b/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts @@ -6,6 +6,7 @@ import { Client as ElasticClient } from '@elastic/elasticsearch'; import { ConfigurationTypes, LogContext } from '@common/enums'; import { NamingDocument } from './types'; import { handleElasticError } from '@services/external/elasticsearch/utils/handle.elastic.error'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class NameReporterService { @@ -16,7 +17,7 @@ export class NameReporterService { constructor( @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService, - private readonly configService: ConfigService, + private readonly configService: ConfigService, @Inject(ELASTICSEARCH_CLIENT_PROVIDER) private readonly client: ElasticClient | undefined ) { diff --git a/src/services/external/excalidraw-backend/adapters/amqp/excalidraw.amqp.server.factory.provider.ts b/src/services/external/excalidraw-backend/adapters/amqp/excalidraw.amqp.server.factory.provider.ts index 137732e492..045b0e65ed 100644 --- a/src/services/external/excalidraw-backend/adapters/amqp/excalidraw.amqp.server.factory.provider.ts +++ b/src/services/external/excalidraw-backend/adapters/amqp/excalidraw.amqp.server.factory.provider.ts @@ -24,6 +24,7 @@ import { serverBroadcastEventAmqpHandler, serverVolatileBroadcastEventAmqpHandler, } from './handlers'; +import { AlkemioConfig } from '@src/types'; export const ExcalidrawAmqpServerFactoryProvider: FactoryProvider = { provide: EXCALIDRAW_SERVER, @@ -38,7 +39,7 @@ export const ExcalidrawAmqpServerFactoryProvider: FactoryProvider = { useFactory: async ( appId: string, logger: LoggerService, - configService: ConfigService, + configService: ConfigService, excalidrawEventPublisher: ExcalidrawEventPublisherService, excalidrawEventSubscriber: ExcalidrawEventSubscriberService ) => @@ -54,7 +55,7 @@ export const ExcalidrawAmqpServerFactoryProvider: FactoryProvider = { const factory = async ( appId: string, logger: LoggerService, - configService: ConfigService, + configService: ConfigService, excalidrawEventPublisher: ExcalidrawEventPublisherService, excalidrawEventSubscriber: ExcalidrawEventSubscriberService ): Promise | never => { diff --git a/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts b/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts index 6020d7d381..d80ecbd958 100644 --- a/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts +++ b/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts @@ -14,6 +14,7 @@ import { AuthenticationService } from '@core/authentication/authentication.servi import { AuthorizationService } from '@core/authorization/authorization.service'; import { WhiteboardService } from '@domain/common/whiteboard'; import { getExcalidrawBaseServerOrFail } from '../../utils/get.excalidraw.base.server'; +import { AlkemioConfig } from '@src/types'; export const ExcalidrawRedisServerFactoryProvider: FactoryProvider = { provide: EXCALIDRAW_SERVER, @@ -28,14 +29,14 @@ export const ExcalidrawRedisServerFactoryProvider: FactoryProvider = { useFactory: async ( appId: string, logger: LoggerService, - configService: ConfigService + configService: ConfigService ) => factory(appId, logger, configService), }; const factory = async ( appId: string, logger: LoggerService, - configService: ConfigService + configService: ConfigService ) => { const { host, port } = configService.get(ConfigurationTypes.STORAGE).redis; diff --git a/src/services/external/excalidraw-backend/excalidraw.server.ts b/src/services/external/excalidraw-backend/excalidraw.server.ts index d959f88cbd..46e346f5e4 100644 --- a/src/services/external/excalidraw-backend/excalidraw.server.ts +++ b/src/services/external/excalidraw-backend/excalidraw.server.ts @@ -64,6 +64,7 @@ import { resetCollaboratorModeDebounceWait, } from './types/defaults'; import { SaveResponse } from './types/save.reponse'; +import { AlkemioConfig } from '@src/types'; type SaveMessageOpts = { timeout: number }; type RoomTimers = Map; @@ -85,7 +86,7 @@ export class ExcalidrawServer { @Inject(APP_ID) private appId: string, @Inject(WINSTON_MODULE_NEST_PROVIDER) private logger: LoggerService, @Inject(EXCALIDRAW_SERVER) private wsServer: SocketIoServer, - private configService: ConfigService, + private configService: ConfigService, private authService: AuthenticationService, private authorizationService: AuthorizationService, private whiteboardService: WhiteboardService, diff --git a/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts b/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts index 8ca8fb6e44..3aaba60085 100644 --- a/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts +++ b/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts @@ -10,9 +10,10 @@ import { } from '@common/enums'; import { BaseException } from '@common/exceptions/base.exception'; import { SocketIoServer } from '../types/socket.io.server'; +import { AlkemioConfig } from '@src/types'; export const getExcalidrawBaseServerOrFail = ( - configService: ConfigService, + configService: ConfigService, logger: LoggerService, adapterFactory?: typeof Adapter | ((nsp: Namespace) => Adapter) ): SocketIoServer | never => { diff --git a/src/services/external/geo-location/geo.location.service.ts b/src/services/external/geo-location/geo.location.service.ts index aeea9b021a..b613c09add 100644 --- a/src/services/external/geo-location/geo.location.service.ts +++ b/src/services/external/geo-location/geo.location.service.ts @@ -15,6 +15,7 @@ import { GeoInformation } from './geo.information'; import { GeoPluginResponse } from './geo.plugin.response'; import { isLimitExceeded } from './utils/is.limit.exceeded'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; +import { AlkemioConfig } from '@src/types'; const geoServiceCallsKey = 'geo-service-call-limit'; @@ -29,7 +30,7 @@ export class GeoLocationService { @Inject(CACHE_MANAGER) private readonly cacheManager: Cache, private readonly httpService: HttpService, - private readonly configService: ConfigService, + private readonly configService: ConfigService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { const config = configService.get(ConfigurationTypes.INTEGRATIONS)?.geo; diff --git a/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts b/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts index fe1c1921a0..16faf46a66 100644 --- a/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts +++ b/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts @@ -11,11 +11,12 @@ import { SsiVcNotVerifiable } from '@common/exceptions/ssi.vc.not.verifiable'; import { WalletManagerCredentialOfferMetadata } from '@services/adapters/wallet-manager-adapter/dto/wallet.manager.dto.credential.offer.metadata'; import { SsiCredentialTypeNotSupported } from '@common/exceptions/ssi.credential.type.not.supported'; import { SsiIssuerType } from '@common/enums/ssi.issuer.type'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class TrustRegistryAdapter { constructor( - private configService: ConfigService, + private configService: ConfigService, private trustRegistryConfigurationProvider: TrustRegistryConfigurationAdapter, private trustRegistryClaimService: TrustRegistryClaimService ) {} diff --git a/src/services/external/trust-registry/trust.registry.configuration/trust.registry.configuration.adapter.ts b/src/services/external/trust-registry/trust.registry.configuration/trust.registry.configuration.adapter.ts index 5550ed69c8..7085bee552 100644 --- a/src/services/external/trust-registry/trust.registry.configuration/trust.registry.configuration.adapter.ts +++ b/src/services/external/trust-registry/trust.registry.configuration/trust.registry.configuration.adapter.ts @@ -3,11 +3,12 @@ import { ConfigService } from '@nestjs/config'; import { ConfigurationTypes } from '@src/common/enums'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { TrustRegistryCredentialMetadata } from './trust.registry.dto.credential.metadata'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class TrustRegistryConfigurationAdapter { constructor( - private readonly configService: ConfigService, + private readonly configService: ConfigService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} diff --git a/src/services/infrastructure/event-bus/event.bus.module.ts b/src/services/infrastructure/event-bus/event.bus.module.ts index 2ff009bbf4..5b0c5c4928 100644 --- a/src/services/infrastructure/event-bus/event.bus.module.ts +++ b/src/services/infrastructure/event-bus/event.bus.module.ts @@ -5,6 +5,7 @@ import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq'; import { ConfigModule, ConfigService } from '@nestjs/config'; import { ConfigurationTypes } from '@common/enums'; import { IngestSpace } from './commands'; +import { AlkemioConfig } from '@src/types'; @Global() @Module({ @@ -13,7 +14,7 @@ import { IngestSpace } from './commands'; RabbitMQModule.forRootAsync(RabbitMQModule, { imports: [ConfigModule], inject: [ConfigService], - useFactory: (configService: ConfigService) => { + useFactory: (configService: ConfigService) => { const rbmqConfig = configService.get(ConfigurationTypes.MICROSERVICES) .rabbitmq.connection; return { diff --git a/src/services/infrastructure/url-generator/url.generator.service.ts b/src/services/infrastructure/url-generator/url.generator.service.ts index 8a67e3770f..d1b102cade 100644 --- a/src/services/infrastructure/url-generator/url.generator.service.ts +++ b/src/services/infrastructure/url-generator/url.generator.service.ts @@ -22,6 +22,7 @@ import { CommunityContributorType } from '@common/enums/community.contributor.ty import { VirtualContributor } from '@domain/community/virtual-contributor/virtual.contributor.entity'; import { User } from '@domain/community/user/user.entity'; import { Organization } from '@domain/community/organization/organization.entity'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class UrlGeneratorService { @@ -50,7 +51,7 @@ export class UrlGeneratorService { private endpoint_cluster: string; constructor( - private configService: ConfigService, + private configService: ConfigService, @InjectEntityManager('default') private entityManager: EntityManager, @Inject(WINSTON_MODULE_NEST_PROVIDER) diff --git a/src/services/whiteboard-integration/whiteboard.integration.service.ts b/src/services/whiteboard-integration/whiteboard.integration.service.ts index a65efc2e4c..9ff7186cca 100644 --- a/src/services/whiteboard-integration/whiteboard.integration.service.ts +++ b/src/services/whiteboard-integration/whiteboard.integration.service.ts @@ -25,6 +25,7 @@ import { import { ContributionReporterService } from '../external/elasticsearch/contribution-reporter'; import { minCollaboratorsInRoom } from '../external/excalidraw-backend/types/defaults'; import { InfoOutputData } from './outputs/info.output.data'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class WhiteboardIntegrationService { @@ -38,7 +39,7 @@ export class WhiteboardIntegrationService { private readonly contributionReporter: ContributionReporterService, private readonly communityResolver: CommunityResolverService, private readonly activityAdapter: ActivityAdapter, - private readonly configService: ConfigService + private readonly configService: ConfigService ) { this.maxCollaboratorsInRoom = this.configService.get( ConfigurationTypes.COLLABORATION diff --git a/src/types/alkemio.config.ts b/src/types/alkemio.config.ts new file mode 100644 index 0000000000..8b53c3d558 --- /dev/null +++ b/src/types/alkemio.config.ts @@ -0,0 +1,258 @@ +export type AlkemioConfig = { + hosting: { + environment: string; + port: number; + endpoint_cluster: string; + path_api_public_rest: string; + path_api_private_rest: string; + subscriptions: { + enabled: string; + }; + whiteboard_rt: { + port: number; + }; + max_json_payload_size: string; + }; + bootstrap: { + authorization: { + enabled: string; + file: string; + }; + }; + security: { + cors: { + enabled: boolean; + origin: string; + methods: string; + allowed_headers: string; + }; + }; + innovation_hub: { + header: string; + }; + search: { + use_new: boolean; + max_results: number; + index_pattern: string; + }; + identity: { + authentication: { + api_access_enabled: boolean; + cache_ttl: number; + providers: { + ory: { + issuer: string; + jwks_uri: string; + kratos_public_base_url: string; + kratos_public_base_url_server: string; + kratos_admin_base_url_server: string; + earliest_possible_extend: number; + admin_service_account: { + username: string; + password: string; + }; + session_cookie_name: string; + session_extend_enabled: boolean; + }; + }; + }; + }; + monitoring: { + logging: { + console_logging_enabled: boolean; + level: 'debug' | 'verbose' | 'info' | 'log' | 'warn' | 'error'; + profiling_enabled: boolean; + json: boolean; + requests: { + full_logging_enabled: boolean; + headers_logging_enabled: boolean; + }; + responses: { + headers_logging_enabled: boolean; + }; + context_to_file: { + enabled: boolean; + filename: string; + context: string; + }; + }; + sentry: { + enabled: boolean; + endpoint: string; + submit_pii: boolean; + }; + apm: { + rumEnabled: boolean; + endpoint: string; + }; + }; + communications: { + enabled: boolean; + matrix: { + connection_retries: number; + connection_timeout: number; + }; + discussions: { + enabled: boolean; + }; + }; + storage: { + database: { + host: string; + port: number; + username: string; + password: string; + schema: string; + database: string; + charset: string; + logging: boolean; + }; + local_storage: { + path: string; + }; + redis: { + host: string; + port: string; + timeout: number; + }; + }; + microservices: { + rabbitmq: { + connection: { + host: string; + port: number; + user: string; + password: string; + }; + }; + }; + integrations: { + geo: { + rest_endpoint: string; + service_endpoint: string; + cache_entry_ttl: number; + allowed_calls_to_service: number; + allowed_calls_to_service_window: number; + }; + elasticsearch: { + host: string; + api_key: string; + retries: number; + timeout: number; + indices: { + contribution: string; + namings: string; + guidance_usage: string; + }; + tls: { + rejectUnauthorized: boolean; + }; + policies: { + space_name_enrich_policy: string; + }; + }; + }; + notifications: { + enabled: boolean; + }; + collaboration: { + whiteboards: { + enabled: boolean; + contribution_window: number; + save_interval: number; + save_timeout: number; + collaborator_mode_timeout: number; + max_collaborators_in_room: number; + }; + }; + platform: { + terms: string; + privacy: string; + security: string; + support: string; + forumreleases: string; + feedback: string; + about: string; + landing: string; + blog: string; + impact: string; + foundation: string; + contactsupport: string; + switchplan: string; + opensource: string; + releases: string; + help: string; + community: string; + newuser: string; + tips: string; + aup: string; + landing_page: { + enabled: boolean; + }; + guidance_engine: { + enabled: boolean; + }; + }; + ssi: { + enabled: boolean; + issuer_validation_enabled: boolean; + issuers: { + alkemio: { + enabled: boolean; + }; + sovrhd: { + enabled: boolean; + endpoint: string; + credential_types: Array<{ + name: string; + identifier: string; + }>; + }; + }; + credentials: { + the_hague_proof_of_postal_address: SsiCredential; + the_hague_hoplr: SsiCredential; + proof_of_email_address: SsiCredential; + proof_of_community_membership: SsiCredential; + proof_of_alkemio_membership: SsiCredential; + }; + }; +}; + +type SsiCredential> = { + name: string; + issuer: string; + description: string; + schema: string; + types: string[]; + uniqueType: string; + context: TContext; +}; + +type the_hague_proof_of_postal_addressContext = { + addressLine1: string; + addressLine2: string; + postalCode: string; + city: string; + country: string; +}; + +type the_hague_hoplrContext = { + the_hague_hoplr: string; +}; + +type proof_of_email_addressContext = { + emailAddress: string; +}; + +type proof_of_community_membershipContext = { + alkemioUser_userID: string; + alkemioUser_email: string; + communityMember_communityID: string; + communityMember_displayName: string; +}; + +type proof_of_alkemio_membershipContext = { + alkemioUser_userID: string; + alkemioUser_email: string; +}; diff --git a/src/types/index.ts b/src/types/index.ts index eb31495066..c4784a4a13 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,2 +1,3 @@ export * from './graphql'; export * from './entity.relations'; +export * from './alkemio.config'; From 562e2952cd4ee67875a1ea7acc33010dedc94ad4 Mon Sep 17 00:00:00 2001 From: hero101 Date: Tue, 30 Jul 2024 16:52:20 +0300 Subject: [PATCH 08/27] wip --- src/app.module.ts | 239 ++++++++++++------------- src/common/enums/configuration.type.ts | 17 -- src/common/enums/index.ts | 1 - src/main.ts | 38 ++-- 4 files changed, 136 insertions(+), 159 deletions(-) delete mode 100644 src/common/enums/configuration.type.ts diff --git a/src/app.module.ts b/src/app.module.ts index 847ea3f489..67334bfff9 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -6,7 +6,6 @@ import { GraphQLModule } from '@nestjs/graphql'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ApolloDriver, ApolloDriverConfig } from '@nestjs/apollo'; import { CloseCode } from 'graphql-ws'; -import { ConfigurationTypes } from '@common/enums'; import { ValidationPipe } from '@common/pipes/validation.pipe'; import configuration from '@config/configuration'; import { @@ -91,45 +90,42 @@ import { LookupByNameModule } from '@services/api/lookup-by-name'; CacheModule.registerAsync({ isGlobal: true, imports: [ConfigModule], - useFactory: async ( - configService: ConfigService - ) => ({ - store: redisStore, - host: configService.get(ConfigurationTypes.STORAGE)?.redis?.host, - port: configService.get(ConfigurationTypes.STORAGE)?.redis?.port, - redisOptions: { - connectTimeout: - configService.get(ConfigurationTypes.STORAGE)?.redis?.timeout * - 1000, // Connection timeout in milliseconds - }, - }), + useFactory: async (configService: ConfigService) => { + const { host, port, timeout } = configService.get('storage.redis', { + infer: true, + }); + return { + store: redisStore, + host, + port, + redisOptions: { connectTimeout: timeout * 1000 }, // Connection timeout in milliseconds + }; + }, inject: [ConfigService], }), TypeOrmModule.forRootAsync({ name: 'default', imports: [ConfigModule], inject: [ConfigService], - useFactory: async ( - configService: ConfigService - ) => ({ - type: 'mysql', - insecureAuth: true, - synchronize: false, - cache: true, - entities: [join(__dirname, '**', '*.entity.{ts,js}')], - host: configService.get(ConfigurationTypes.STORAGE)?.database?.host, - port: configService.get(ConfigurationTypes.STORAGE)?.database?.port, - charset: configService.get(ConfigurationTypes.STORAGE)?.database - ?.charset, - username: configService.get(ConfigurationTypes.STORAGE)?.database - ?.username, - password: configService.get(ConfigurationTypes.STORAGE)?.database - ?.password, - database: configService.get(ConfigurationTypes.STORAGE)?.database - ?.schema, - logging: configService.get(ConfigurationTypes.STORAGE)?.database - ?.logging, - }), + useFactory: async (configService: ConfigService) => { + const dbOptions = configService.get('storage.database', { + infer: true, + }); + return { + type: 'mysql', + insecureAuth: true, + synchronize: false, + cache: true, + entities: [join(__dirname, '**', '*.entity.{ts,js}')], + host: dbOptions.host, + port: dbOptions.port, + charset: dbOptions.charset, + username: dbOptions.username, + password: dbOptions.password, + database: dbOptions.database, + logging: dbOptions.logging, + }; + }, }), WinstonModule.forRootAsync({ useClass: WinstonConfigService, @@ -138,104 +134,99 @@ import { LookupByNameModule } from '@services/api/lookup-by-name'; driver: ApolloDriver, imports: [ConfigModule], inject: [ConfigService], - useFactory: async ( - configService: ConfigService - ) => ({ - cors: false, // this is to avoid a duplicate cors origin header being created when behind the oathkeeper reverse proxy - uploads: false, - autoSchemaFile: true, - introspection: true, - playground: { - settings: { - 'request.credentials': 'include', - }, - tabs: [ - { - name: 'Me', - endpoint: `${ - configService.get(ConfigurationTypes.HOSTING)?.endpoint_cluster - }/api/private/graphql`, - query: print(meQuery), - }, - { - name: 'Spaces', - endpoint: `${ - configService.get(ConfigurationTypes.HOSTING)?.endpoint_cluster - }/api/private/graphql`, - query: print(spacesQuery), - }, - { - name: 'Configuration', - endpoint: `${ - configService.get(ConfigurationTypes.HOSTING)?.endpoint_cluster - }/api/public/graphql`, - query: print(configQuery), - }, - { - name: 'Server Metadata', - endpoint: `${ - configService.get(ConfigurationTypes.HOSTING)?.endpoint_cluster - }/api/public/graphql`, - query: print(platformMetadataQuery), + useFactory: async (configService: ConfigService) => { + const endpointCluster = configService.get('hosting.endpoint_cluster', { + infer: true, + }); + return { + cors: false, // this is to avoid a duplicate cors origin header being created when behind the oathkeeper reverse proxy + uploads: false, + autoSchemaFile: true, + introspection: true, + playground: { + settings: { + 'request.credentials': 'include', }, - ], - }, - fieldResolverEnhancers: ['guards', 'filters'], - sortSchema: true, - persistedQueries: false, - /*** - * graphql-ws requires passing the request object through the context method - * !!! this is graphql-ws ONLY - */ - context: (ctx: ConnectionContext) => { - if (isWebsocketContext(ctx)) { - return { - req: { - ...ctx.extra.request, - headers: { - ...ctx.extra.request.headers, - ...ctx.connectionParams?.headers, - }, - connectionParams: ctx.connectionParams, + tabs: [ + { + name: 'Me', + endpoint: `${endpointCluster}/api/private/graphql`, + query: print(meQuery), }, - }; - } - - return { req: ctx.req }; - }, - subscriptions: { - 'subscriptions-transport-ws': { - /*** - * subscriptions-transport-ws required passing the request object - * through the onConnect method - */ - onConnect: ( - connectionParams: Record, - websocket: SubscriptionsTransportWsWebsocket // couldn't find a better type - ) => { + { + name: 'Spaces', + endpoint: `${endpointCluster}/api/private/graphql`, + query: print(spacesQuery), + }, + { + name: 'Configuration', + endpoint: `${endpointCluster}/api/public/graphql`, + query: print(configQuery), + }, + { + name: 'Server Metadata', + endpoint: `${endpointCluster}/api/public/graphql`, + query: print(platformMetadataQuery), + }, + ], + }, + fieldResolverEnhancers: ['guards', 'filters'], + sortSchema: true, + persistedQueries: false, + /*** + * graphql-ws requires passing the request object through the context method + * !!! this is graphql-ws ONLY + */ + context: (ctx: ConnectionContext) => { + if (isWebsocketContext(ctx)) { return { - req: { headers: websocket?.upgradeReq?.headers }, + req: { + ...ctx.extra.request, + headers: { + ...ctx.extra.request.headers, + ...ctx.connectionParams?.headers, + }, + connectionParams: ctx.connectionParams, + }, }; - }, + } + + return { req: ctx.req }; }, - 'graphql-ws': { - onNext: (ctx, message, args, result) => { - const context = args.contextValue as IGraphQLContext; - const expiry = context.req.user.expiry; - // if the session has expired, close the socket - if (expiry && expiry < Date.now()) { - (ctx as WebsocketContext).extra.socket.close( - CloseCode.Unauthorized, - 'Session expired' - ); - return; - } + subscriptions: { + 'subscriptions-transport-ws': { + /*** + * subscriptions-transport-ws required passing the request object + * through the onConnect method + */ + onConnect: ( + connectionParams: Record, + websocket: SubscriptionsTransportWsWebsocket // couldn't find a better type + ) => { + return { + req: { headers: websocket?.upgradeReq?.headers }, + }; + }, + }, + 'graphql-ws': { + onNext: (ctx, message, args, result) => { + const context = args.contextValue as IGraphQLContext; + const expiry = context.req.user.expiry; + // if the session has expired, close the socket + if (expiry && expiry < Date.now()) { + (ctx as WebsocketContext).extra.socket.close( + CloseCode.Unauthorized, + 'Session expired' + ); + return; + } - return result; + return result; + }, }, }, - }, - }), + }; + }, }), ScalarsModule, AuthenticationModule, diff --git a/src/common/enums/configuration.type.ts b/src/common/enums/configuration.type.ts deleted file mode 100644 index 131dc7a6c6..0000000000 --- a/src/common/enums/configuration.type.ts +++ /dev/null @@ -1,17 +0,0 @@ -export enum ConfigurationTypes { - HOSTING = 'hosting', - BOOTSTRAP = 'bootstrap', - MONITORING = 'monitoring', - SECURITY = 'security', - IDENTITY = 'identity', - COMMUNICATIONS = 'communications', - STORAGE = 'storage', - PLATFORM = 'platform', - NOTIFICATIONS = 'notifications', - MICROSERVICES = 'microservices', - COLLABORATION = 'collaboration', - SSI = 'ssi', - INTEGRATIONS = 'integrations', - INNOVATION_HUB = 'innovation_hub', - SEARCH = 'search', -} diff --git a/src/common/enums/index.ts b/src/common/enums/index.ts index 1fd5825c7d..c0cdc5bd58 100644 --- a/src/common/enums/index.ts +++ b/src/common/enums/index.ts @@ -1,7 +1,6 @@ export * from './logging.context'; export * from './alkemio.error.status'; export * from './authentication.provider'; -export * from './configuration.type'; export * from './authorization.credential'; export * from './authorization.credential.global'; export * from './authorization.privilege'; diff --git a/src/main.ts b/src/main.ts index b0666dfc8a..491cc9298a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,7 +8,7 @@ import { BootstrapService } from './core/bootstrap/bootstrap.service'; import { faviconMiddleware } from './core/middleware/favicon.middleware'; import { useContainer } from 'class-validator'; import { graphqlUploadExpress } from 'graphql-upload'; -import { ConfigurationTypes, MessagingQueue } from '@common/enums'; +import { MessagingQueue } from '@common/enums'; import { json } from 'body-parser'; import cookieParser from 'cookie-parser'; import { MicroserviceOptions, Transport } from '@nestjs/microservices'; @@ -34,14 +34,15 @@ const bootstrap = async () => { useContainer(app.select(AppModule), { fallbackOnErrors: true }); await bootstrapService.bootstrap(); - const corsEnabled = configService.get(ConfigurationTypes.SECURITY).cors - .enabled; - if (corsEnabled) { + const { enabled, methods, origin, allowed_headers } = configService.get( + 'security.cors', + { infer: true } + ); + if (enabled) { app.enableCors({ - origin: configService.get(ConfigurationTypes.SECURITY)?.cors?.origin, - allowedHeaders: configService.get(ConfigurationTypes.SECURITY)?.cors - ?.allowed_headers, - methods: configService.get(ConfigurationTypes.SECURITY)?.cors?.methods, + origin, + allowedHeaders: allowed_headers, + methods, }); } @@ -55,24 +56,27 @@ const bootstrap = async () => { app.use( graphqlUploadExpress({ - maxFileSize: configService.get(ConfigurationTypes.STORAGE)?.file - ?.max_file_size, + maxFileSize: configService.get(ConfigurationTypes.STORAGE, { + infer: true, + })?.file?.max_file_size, }) ); + const { max_json_payload_size, port } = configService.get('hosting', { + infer: true, + }); app.use( json({ - limit: configService.get(ConfigurationTypes.HOSTING) - ?.max_json_payload_size, + limit: max_json_payload_size, }) ); - await app.listen( - configService.get(ConfigurationTypes.HOSTING)?.port as number - ); + await app.listen(port); - const connectionOptions = configService.get(ConfigurationTypes.MICROSERVICES) - ?.rabbitmq?.connection; + const connectionOptions = configService.get( + 'microservices.rabbitmq.connection', + { infer: true } + ); const heartbeat = process.env.NODE_ENV === 'production' ? 30 : 120; const amqpEndpoint = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=${heartbeat}`; From d6d4d9d12aa0bafd2b7c174dea339b33e64c7e0c Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Wed, 31 Jul 2024 16:50:54 +0300 Subject: [PATCH 09/27] wip --- src/core/authentication/ory.api.strategy.ts | 9 +++------ src/core/bootstrap/bootstrap.service.ts | 2 +- .../microservices/auth.reset.service.factory.ts | 6 ++---- .../matrix.adapter.service.factory.ts | 6 ++---- .../microservices/notifications.service.factory.ts | 6 ++---- src/core/microservices/subscription.factory.ts | 6 ++---- .../wallet-manager.service.factory.ts | 6 ++---- src/core/middleware/request.logger.middleware.ts | 10 +++------- src/core/middleware/session.extend.middleware.ts | 14 ++++---------- src/main.ts | 2 +- .../external/geo-location/geo.location.service.ts | 4 ++-- .../trust.registry.adapter.ts | 10 +++------- .../trust.registry.configuration.adapter.ts | 3 +-- .../infrastructure/event-bus/event.bus.module.ts | 5 ++--- .../url-generator/url.generator.service.ts | 5 +---- .../whiteboard.integration.service.ts | 5 +---- 16 files changed, 32 insertions(+), 67 deletions(-) diff --git a/src/core/authentication/ory.api.strategy.ts b/src/core/authentication/ory.api.strategy.ts index bdd5d36c65..f0eee0ca82 100644 --- a/src/core/authentication/ory.api.strategy.ts +++ b/src/core/authentication/ory.api.strategy.ts @@ -4,7 +4,7 @@ import { PassportStrategy } from '@nestjs/passport'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { Strategy } from 'passport-custom'; import { Configuration, FrontendApi } from '@ory/kratos-client'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { ApiRestrictedAccessException } from '@common/exceptions/auth'; import { AuthenticationService } from './authentication.service'; import { OryDefaultIdentitySchema } from './ory.default.identity.schema'; @@ -25,9 +25,7 @@ export class OryApiStrategy extends PassportStrategy( ) { super(); - const kratosPublicBaseUrl = this.configService.get( - ConfigurationTypes.IDENTITY - ).authentication.providers.ory.kratos_public_base_url_server; + const kratosPublicBaseUrl = this.configService.get('identity.authentication.providers.ory.kratos_public_base_url_server', { infer: true }); this.kratosClient = new FrontendApi( new Configuration({ @@ -37,8 +35,7 @@ export class OryApiStrategy extends PassportStrategy( } async validate(payload: IncomingMessage) { - const apiAccessEnabled = this.configService.get(ConfigurationTypes.IDENTITY) - .authentication.api_access_enabled; + const apiAccessEnabled = this.configService.get('identity.authentication.api_access_enabled', { infer: true }); if (!apiAccessEnabled) { throw new ApiRestrictedAccessException('API access is restricted!'); diff --git a/src/core/bootstrap/bootstrap.service.ts b/src/core/bootstrap/bootstrap.service.ts index e8636bf09d..166ce9cd93 100644 --- a/src/core/bootstrap/bootstrap.service.ts +++ b/src/core/bootstrap/bootstrap.service.ts @@ -8,7 +8,7 @@ import fs from 'fs'; import * as defaultRoles from '@templates/authorization-bootstrap.json'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { Profiling } from '@common/decorators'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { BootstrapException } from '@common/exceptions/bootstrap.exception'; import { UserAuthorizationService } from '@domain/community/user/user.service.authorization'; import { diff --git a/src/core/microservices/auth.reset.service.factory.ts b/src/core/microservices/auth.reset.service.factory.ts index 9474c63101..e023f43c29 100644 --- a/src/core/microservices/auth.reset.service.factory.ts +++ b/src/core/microservices/auth.reset.service.factory.ts @@ -1,4 +1,4 @@ -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; @@ -9,9 +9,7 @@ export async function authResetServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService.get( - ConfigurationTypes.MICROSERVICES - )?.rabbitmq; + const rabbitMqOptions = configService?.get('microservices.rabbitmq', { infer: true }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/core/microservices/matrix.adapter.service.factory.ts b/src/core/microservices/matrix.adapter.service.factory.ts index e031bf3aae..77310c89bb 100644 --- a/src/core/microservices/matrix.adapter.service.factory.ts +++ b/src/core/microservices/matrix.adapter.service.factory.ts @@ -1,4 +1,4 @@ -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; @@ -9,9 +9,7 @@ export async function matrixAdapterServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService.get( - ConfigurationTypes.MICROSERVICES - )?.rabbitmq; + const rabbitMqOptions = configService.get('microservices.rabbitmq', { infer: true }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/core/microservices/notifications.service.factory.ts b/src/core/microservices/notifications.service.factory.ts index 98fd46dd9a..1e631208c8 100644 --- a/src/core/microservices/notifications.service.factory.ts +++ b/src/core/microservices/notifications.service.factory.ts @@ -1,4 +1,4 @@ -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; @@ -9,9 +9,7 @@ export async function notificationsServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService.get( - ConfigurationTypes.MICROSERVICES - )?.rabbitmq; + const rabbitMqOptions = configService?.get('microservices.rabbitmq', { infer: true }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/core/microservices/subscription.factory.ts b/src/core/microservices/subscription.factory.ts index 7cdfd6d5c3..1f752a1832 100644 --- a/src/core/microservices/subscription.factory.ts +++ b/src/core/microservices/subscription.factory.ts @@ -3,7 +3,7 @@ import { AMQPPubSub } from 'graphql-amqp-subscriptions'; import { PubSubEngine } from 'graphql-subscriptions'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { AlkemioConfig } from '@src/types'; export async function subscriptionFactory( @@ -12,9 +12,7 @@ export async function subscriptionFactory( exchangeName: string, queueName: string ): Promise { - const rabbitMqOptions = configService?.get( - ConfigurationTypes.MICROSERVICES - )?.rabbitmq; + const rabbitMqOptions = configService?.get('microservices.rabbitmq', { infer: true }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; diff --git a/src/core/microservices/wallet-manager.service.factory.ts b/src/core/microservices/wallet-manager.service.factory.ts index 99a31539c6..36a6f3f4c9 100644 --- a/src/core/microservices/wallet-manager.service.factory.ts +++ b/src/core/microservices/wallet-manager.service.factory.ts @@ -1,4 +1,4 @@ -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; @@ -9,9 +9,7 @@ export async function walletManagerServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService.get( - ConfigurationTypes.MICROSERVICES - )?.rabbitmq; + const rabbitMqOptions = configService.get('microservices.rabbitmq', { infer: true }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/core/middleware/request.logger.middleware.ts b/src/core/middleware/request.logger.middleware.ts index bf24d7a02a..1a1569aa4d 100644 --- a/src/core/middleware/request.logger.middleware.ts +++ b/src/core/middleware/request.logger.middleware.ts @@ -7,7 +7,7 @@ import { import { Request, Response, NextFunction } from 'express'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { ConfigService } from '@nestjs/config'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { AlkemioConfig } from '@src/types'; @Injectable() @@ -19,15 +19,11 @@ export class RequestLoggerMiddleware implements NestMiddleware { private readonly configService: ConfigService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { - const reqLoggingConfig = this.configService.get( - ConfigurationTypes.MONITORING - )?.logging?.requests; + const reqLoggingConfig = this.configService.get('monitoring.logging.requests', { infer: true }); this.requestFullLogging = reqLoggingConfig?.full_logging_enabled; this.requestHeadersLogging = reqLoggingConfig?.headers_logging_enabled; - const resLoggingConfig = this.configService.get( - ConfigurationTypes.MONITORING - )?.logging?.responses; + const resLoggingConfig = this.configService.get('monitoring.logging.responses', { infer: true }); this.responseHeadersLogging = resLoggingConfig?.headers_logging_enabled; } diff --git a/src/core/middleware/session.extend.middleware.ts b/src/core/middleware/session.extend.middleware.ts index 36f1f79afd..babf5fa169 100644 --- a/src/core/middleware/session.extend.middleware.ts +++ b/src/core/middleware/session.extend.middleware.ts @@ -8,7 +8,7 @@ import { ConfigService } from '@nestjs/config'; import { Request, Response, NextFunction } from 'express'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { AuthenticationService } from '@core/authentication/authentication.service'; -import { ConfigurationTypes, LogContext } from '@src/common/enums'; +import { LogContext } from '@src/common/enums'; import { getSessionFromJwt } from '@common/utils'; import { Configuration, FrontendApi, Session } from '@ory/kratos-client'; import { AlkemioConfig } from '@src/types'; @@ -24,17 +24,11 @@ export class SessionExtendMiddleware implements NestMiddleware { private readonly authService: AuthenticationService, private readonly configService: ConfigService ) { - this.SESSION_COOKIE_NAME = this.configService.get( - ConfigurationTypes.IDENTITY - )?.authentication.providers.ory.session_cookie_name; + this.SESSION_COOKIE_NAME = this.configService.get('identity.authentication.providers.ory.session_cookie_name', { infer: true }); - this.enabled = this.configService.get( - ConfigurationTypes.IDENTITY - )?.authentication.providers.ory.session_extend_enabled; + this.enabled = this.configService.get('identity.authentication.providers.ory.session_cookie_name', { infer: true }); - const kratosPublicBaseUrl = this.configService.get( - ConfigurationTypes.IDENTITY - ).authentication.providers.ory.kratos_public_base_url_server; + const kratosPublicBaseUrl = this.configService.get('identity.authentication.providers.ory.kratos_public_base_url_server', { infer: true }); this.kratosClient = new FrontendApi( new Configuration({ diff --git a/src/main.ts b/src/main.ts index 491cc9298a..e4cd66b6a5 100644 --- a/src/main.ts +++ b/src/main.ts @@ -58,7 +58,7 @@ const bootstrap = async () => { graphqlUploadExpress({ maxFileSize: configService.get(ConfigurationTypes.STORAGE, { infer: true, - })?.file?.max_file_size, + })?.file?.max_file_size, // todo: this does not exist in the config }) ); diff --git a/src/services/external/geo-location/geo.location.service.ts b/src/services/external/geo-location/geo.location.service.ts index b613c09add..449fc4c7bd 100644 --- a/src/services/external/geo-location/geo.location.service.ts +++ b/src/services/external/geo-location/geo.location.service.ts @@ -10,7 +10,7 @@ import { GeoServiceRequestLimitExceededException, GeoServiceNotAvailableException, } from '@common/exceptions/geo'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { GeoInformation } from './geo.information'; import { GeoPluginResponse } from './geo.plugin.response'; import { isLimitExceeded } from './utils/is.limit.exceeded'; @@ -33,7 +33,7 @@ export class GeoLocationService { private readonly configService: ConfigService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { - const config = configService.get(ConfigurationTypes.INTEGRATIONS)?.geo; + const config = configService.get('integrations.geo', { infer: true }); this.endpoint = config.service_endpoint; this.allowedCallsToService = config.allowed_calls_to_service; this.allowedCallsToServiceWindow = config.allowed_calls_to_service_window; diff --git a/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts b/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts index 16faf46a66..3c015a6deb 100644 --- a/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts +++ b/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { randomUUID } from 'crypto'; import { ConfigService } from '@nestjs/config'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { RestEndpoint } from '@common/enums/rest.endpoint'; import { TrustRegistryCredentialMetadata } from '../trust.registry.configuration/trust.registry.dto.credential.metadata'; import { TrustRegistryConfigurationAdapter } from '../trust.registry.configuration/trust.registry.configuration.adapter'; @@ -135,11 +135,7 @@ export class TrustRegistryAdapter { } private generatePublicRestApiUrl() { - const url = `${ - this.configService.get(ConfigurationTypes.HOSTING)?.endpoint_cluster - }${ - this.configService.get(ConfigurationTypes.HOSTING)?.path_api_public_rest - }`; - return url; + const { endpoint_cluster, path_api_public_rest } = this.configService.get('hosting', { infer: true }); + return `${endpoint_cluster}${path_api_public_rest}`; } } diff --git a/src/services/external/trust-registry/trust.registry.configuration/trust.registry.configuration.adapter.ts b/src/services/external/trust-registry/trust.registry.configuration/trust.registry.configuration.adapter.ts index 7085bee552..598f8a8a4e 100644 --- a/src/services/external/trust-registry/trust.registry.configuration/trust.registry.configuration.adapter.ts +++ b/src/services/external/trust-registry/trust.registry.configuration/trust.registry.configuration.adapter.ts @@ -1,6 +1,5 @@ import { Inject, Injectable, LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { ConfigurationTypes } from '@src/common/enums'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { TrustRegistryCredentialMetadata } from './trust.registry.dto.credential.metadata'; import { AlkemioConfig } from '@src/types'; @@ -15,7 +14,7 @@ export class TrustRegistryConfigurationAdapter { getCredentials(): TrustRegistryCredentialMetadata[] { const credentials: TrustRegistryCredentialMetadata[] = - this.configService.get(ConfigurationTypes.SSI).credentials; + this.configService.get('ssi.credentials', { infer: true }); const credentialValues: TrustRegistryCredentialMetadata[] = Object.values(credentials); diff --git a/src/services/infrastructure/event-bus/event.bus.module.ts b/src/services/infrastructure/event-bus/event.bus.module.ts index 5b0c5c4928..84321c14e8 100644 --- a/src/services/infrastructure/event-bus/event.bus.module.ts +++ b/src/services/infrastructure/event-bus/event.bus.module.ts @@ -3,7 +3,6 @@ import { CqrsModule, EventBus } from '@nestjs/cqrs'; import { Publisher } from './publisher'; import { RabbitMQModule } from '@golevelup/nestjs-rabbitmq'; import { ConfigModule, ConfigService } from '@nestjs/config'; -import { ConfigurationTypes } from '@common/enums'; import { IngestSpace } from './commands'; import { AlkemioConfig } from '@src/types'; @@ -15,8 +14,8 @@ import { AlkemioConfig } from '@src/types'; imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => { - const rbmqConfig = configService.get(ConfigurationTypes.MICROSERVICES) - .rabbitmq.connection; + const rbmqConfig = configService.get('microservices.rabbitmq.connection', { infer: true }); + return { uri: `amqp://${rbmqConfig.user}:${rbmqConfig.password}@${rbmqConfig.host}:${rbmqConfig.port}`, connectionInitOptions: { wait: false }, diff --git a/src/services/infrastructure/url-generator/url.generator.service.ts b/src/services/infrastructure/url-generator/url.generator.service.ts index d1b102cade..f3e9935173 100644 --- a/src/services/infrastructure/url-generator/url.generator.service.ts +++ b/src/services/infrastructure/url-generator/url.generator.service.ts @@ -1,5 +1,4 @@ import { LogContext, ProfileType } from '@common/enums'; -import { ConfigurationTypes } from '@common/enums/configuration.type'; import { EntityNotFoundException, RelationshipNotFoundException, @@ -58,9 +57,7 @@ export class UrlGeneratorService { private readonly logger: LoggerService, @Inject(CACHE_MANAGER) private readonly cacheManager: Cache ) { - this.endpoint_cluster = this.configService.get( - ConfigurationTypes.HOSTING - )?.endpoint_cluster; + this.endpoint_cluster = this.configService.get('hosting.endpoint_cluster', { infer: true }); } private getUrlIdCacheKey(entityId: string): string { diff --git a/src/services/whiteboard-integration/whiteboard.integration.service.ts b/src/services/whiteboard-integration/whiteboard.integration.service.ts index 9ff7186cca..a920c60168 100644 --- a/src/services/whiteboard-integration/whiteboard.integration.service.ts +++ b/src/services/whiteboard-integration/whiteboard.integration.service.ts @@ -8,7 +8,6 @@ import { UserService } from '@domain/community/user/user.service'; import { IVerifiedCredential } from '@domain/agent/verified-credential/verified.credential.interface'; import { AuthorizationPrivilege, - ConfigurationTypes, LogContext, } from '@common/enums'; import { EntityNotInitializedException } from '@common/exceptions'; @@ -41,9 +40,7 @@ export class WhiteboardIntegrationService { private readonly activityAdapter: ActivityAdapter, private readonly configService: ConfigService ) { - this.maxCollaboratorsInRoom = this.configService.get( - ConfigurationTypes.COLLABORATION - )?.whiteboards?.max_collaborators_in_room; + this.maxCollaboratorsInRoom = this.configService.get('collaboration.whiteboards.max_collaborators_in_room', { infer: true }); } public async accessGranted(data: AccessGrantedInputData): Promise { From 1961fcc110f0758b159cb297166ed5d7c4431af6 Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Wed, 31 Jul 2024 17:50:25 +0300 Subject: [PATCH 10/27] wip --- ...ntributor.engine.expert.service.factory.ts | 6 +- ...ributor.engine.guidance.service.factory.ts | 6 +- .../agent/agent/agent.resolver.fields.ts | 16 +-- src/domain/agent/agent/agent.service.ts | 12 +- .../storage/document/document.service.ts | 6 +- .../configuration/config/config.service.ts | 3 +- .../communication.adapter.ts | 6 +- .../notification.payload.builder.ts | 43 +++--- .../adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts | 5 +- .../adapters/storage/ipfs/ipfs.module.ts | 8 -- .../storage/ipfs/ipfs.service._spec.ts | 29 ---- .../adapters/storage/ipfs/ipfs.service.ts | 129 ------------------ .../local-storage/local.storage.adapter.ts | 5 +- .../ai-server/ai.server.resolver.mutations.ts | 6 +- .../ai-server/ai-server/ai.server.service.ts | 8 +- .../chat-guidance/chat.guidance.service.ts | 6 +- .../api/search/v1/search.resolver.queries.ts | 5 +- .../v2/extract/search.extract.service.ts | 9 +- .../api/search/v2/ingest/get.index.pattern.ts | 8 +- .../contribution.reporter.service.ts | 10 +- .../elasticsearch.client.factory.ts | 5 +- .../guidance.reporter.service.ts | 10 +- .../name-reporter/name.reporter.service.ts | 10 +- ...xcalidraw.redis.server.factory.provider.ts | 3 +- .../excalidraw-backend/excalidraw.server.ts | 8 +- .../utils/get.excalidraw.base.server.ts | 3 +- src/types/alkemio.config.ts | 5 + 27 files changed, 74 insertions(+), 296 deletions(-) delete mode 100644 src/services/adapters/storage/ipfs/ipfs.module.ts delete mode 100644 src/services/adapters/storage/ipfs/ipfs.service._spec.ts delete mode 100644 src/services/adapters/storage/ipfs/ipfs.service.ts diff --git a/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts b/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts index 64be82f8ea..9757397601 100644 --- a/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts +++ b/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts @@ -1,4 +1,4 @@ -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; @@ -9,9 +9,7 @@ export async function virtualContributorEngineExpertServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService.get( - ConfigurationTypes.MICROSERVICES - )?.rabbitmq; + const rabbitMqOptions = configService.get('microservices.rabbitmq', { infer: true }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts b/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts index 313f618767..dbcab15196 100644 --- a/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts +++ b/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts @@ -1,4 +1,4 @@ -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; @@ -9,9 +9,7 @@ export async function virtualContributorEngineGuidanceServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService.get( - ConfigurationTypes.MICROSERVICES - )?.rabbitmq; + const rabbitMqOptions = configService.get('microservices.rabbitmq', { infer: true }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/domain/agent/agent/agent.resolver.fields.ts b/src/domain/agent/agent/agent.resolver.fields.ts index 48354a1dda..3519637494 100644 --- a/src/domain/agent/agent/agent.resolver.fields.ts +++ b/src/domain/agent/agent/agent.resolver.fields.ts @@ -1,12 +1,7 @@ import { UseGuards } from '@nestjs/common'; -import { Resolver } from '@nestjs/graphql'; -import { Parent, ResolveField } from '@nestjs/graphql'; +import { Parent, ResolveField, Resolver } from '@nestjs/graphql'; import { AgentService } from './agent.service'; -import { - AuthorizationPrivilege, - ConfigurationTypes, - LogContext, -} from '@common/enums'; +import { AuthorizationPrivilege, LogContext } from '@common/enums'; import { AuthorizationAgentPrivilege, Profiling } from '@common/decorators'; import { Agent, IAgent } from '@domain/agent/agent'; import { GraphqlGuard } from '@core/authorization'; @@ -29,14 +24,13 @@ export class AgentResolverFields { description: 'The Verfied Credentials for this Agent.', }) @Profiling.api - async verifiedCredentials( + public verifiedCredentials( @Parent() agent: Agent ): Promise { - const ssiEnabled = this.configService.get(ConfigurationTypes.SSI).enabled; + const ssiEnabled = this.configService.get('ssi.enabled', { infer: true }); if (!ssiEnabled) { throw new NotEnabledException('SSI is not enabled', LogContext.SSI); } - const result = await this.agentService.getVerifiedCredentials(agent.id); - return result; + return this.agentService.getVerifiedCredentials(agent.id); } } diff --git a/src/domain/agent/agent/agent.service.ts b/src/domain/agent/agent/agent.service.ts index c6b4c298e3..2267293852 100644 --- a/src/domain/agent/agent/agent.service.ts +++ b/src/domain/agent/agent/agent.service.ts @@ -1,7 +1,7 @@ import { PubSubEngine } from 'graphql-subscriptions'; import { SUBSCRIPTION_PROFILE_VERIFIED_CREDENTIAL } from '@common/constants'; import { Profiling } from '@common/decorators/profiling.decorator'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { AuthenticationException, EntityNotFoundException, @@ -69,9 +69,7 @@ export class AgentService { @Inject(SUBSCRIPTION_PROFILE_VERIFIED_CREDENTIAL) private subscriptionVerifiedCredentials: PubSubEngine ) { - this.cache_ttl = this.configService.get( - ConfigurationTypes.IDENTITY - ).authentication.cache_ttl; + this.cache_ttl = this.configService.get('identity.authentication.cache_ttl', { infer: true }); } async createAgent(inputData: CreateAgentInput): Promise { @@ -79,7 +77,7 @@ export class AgentService { agent.credentials = []; agent.authorization = new AuthorizationPolicy(); - const ssiEnabled = this.configService.get(ConfigurationTypes.SSI).enabled; + const ssiEnabled = this.configService.get('ssi.enabled', { infer: true }); if (ssiEnabled) { return await this.createDidOnAgent(agent); @@ -552,9 +550,7 @@ export class AgentService { } validateTrustedIssuerOrFail(vcName: string, vcToBeStored: any) { - const trustedIssuerValidationEnabled = this.configService.get( - ConfigurationTypes.SSI - ).issuer_validation_enabled; + const trustedIssuerValidationEnabled = this.configService.get('ssi.issuer_validation_enabled', { infer: true }); if (!trustedIssuerValidationEnabled) return; const trustedIssuers = diff --git a/src/domain/storage/document/document.service.ts b/src/domain/storage/document/document.service.ts index 561d7ae2d8..ee73a74f60 100644 --- a/src/domain/storage/document/document.service.ts +++ b/src/domain/storage/document/document.service.ts @@ -4,7 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { FindOneOptions, Repository } from 'typeorm'; import { EntityNotFoundException } from '@common/exceptions'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { AuthorizationPolicy } from '@domain/common/authorization-policy'; import { AuthorizationPolicyService } from '@domain/common/authorization-policy/authorization.policy.service'; import { DeleteDocumentInput } from './dto/document.dto.delete'; @@ -202,9 +202,7 @@ export class DocumentService { } private getDocumentsBaseUrlPath(): string { - const { endpoint_cluster, path_api_private_rest } = this.configService.get( - ConfigurationTypes.HOSTING - ); + const { endpoint_cluster, path_api_private_rest } = this.configService.get('hosting', { infer: true }); return `${endpoint_cluster}${path_api_private_rest}/storage/document`; } diff --git a/src/platform/configuration/config/config.service.ts b/src/platform/configuration/config/config.service.ts index 5af6f16a47..cea4bd59d6 100644 --- a/src/platform/configuration/config/config.service.ts +++ b/src/platform/configuration/config/config.service.ts @@ -2,7 +2,6 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { IConfig } from './config.interface'; import { IAuthenticationProviderConfig } from './authentication/providers/authentication.provider.config.interface'; -import { ConfigurationTypes } from '@common/enums'; import { IOryConfig } from './authentication/providers/ory/ory.config.interface'; import { PlatformFeatureFlagName } from '@common/enums/platform.feature.flag.name'; import { AlkemioConfig } from '@src/types'; @@ -13,7 +12,7 @@ export class KonfigService { async getConfig(): Promise { const domain = new URL( - this.configService.get(ConfigurationTypes.HOSTING)?.endpoint_cluster + this.configService.get('hosting.endpoint_cluster', { infer: true }) ).hostname; const sentryConfig = this.configService.get( diff --git a/src/services/adapters/communication-adapter/communication.adapter.ts b/src/services/adapters/communication-adapter/communication.adapter.ts index 6377fade6f..00f6f50ad1 100644 --- a/src/services/adapters/communication-adapter/communication.adapter.ts +++ b/src/services/adapters/communication-adapter/communication.adapter.ts @@ -1,6 +1,6 @@ import { firstValueFrom, TimeoutError, Observable } from 'rxjs'; import { catchError, retry, timeout } from 'rxjs/operators'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { MatrixEntityNotFoundException } from '@common/exceptions'; import { DirectRoomResult } from '@domain/community/user/dto/user.dto.communication.room.direct.result'; import { Inject, Injectable, LoggerService } from '@nestjs/common'; @@ -79,9 +79,7 @@ export class CommunicationAdapter { private configService: ConfigService, @Inject(MATRIX_ADAPTER_SERVICE) private matrixAdapterClient: ClientProxy ) { - const communications = this.configService.get( - ConfigurationTypes.COMMUNICATIONS - ); + const communications = this.configService.get('communications'); this.enabled = communications?.enabled; this.timeout = +communications?.matrix?.connection_timeout * 1000; this.retries = +communications?.matrix?.connection_retries; diff --git a/src/services/adapters/notification-adapter/notification.payload.builder.ts b/src/services/adapters/notification-adapter/notification.payload.builder.ts index 6434938558..1913732733 100644 --- a/src/services/adapters/notification-adapter/notification.payload.builder.ts +++ b/src/services/adapters/notification-adapter/notification.payload.builder.ts @@ -1,4 +1,4 @@ -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { EntityNotFoundException } from '@common/exceptions'; import { NotificationEventException } from '@common/exceptions/notification.event.exception'; import { ICommunity } from '@domain/community/community'; @@ -8,32 +8,32 @@ import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { Repository } from 'typeorm'; import { Post } from '@domain/collaboration/post/post.entity'; import { - CollaborationPostCreatedEventPayload, - CollaborationPostCommentEventPayload, + BaseEventPayload, CollaborationCalloutPublishedEventPayload, - PlatformUserRegistrationEventPayload, - PlatformUserRemovedEventPayload, - CommunityNewMemberPayload, - CommunicationUpdateEventPayload, - PlatformForumDiscussionCreatedEventPayload, - CommunicationUserMessageEventPayload, - CommunicationOrganizationMessageEventPayload, + CollaborationDiscussionCommentEventPayload, + CollaborationPostCommentEventPayload, + CollaborationPostCreatedEventPayload, + CollaborationWhiteboardCreatedEventPayload, + CommentReplyEventPayload, CommunicationCommunityLeadsMessageEventPayload, - CommunicationUserMentionEventPayload, CommunicationOrganizationMentionEventPayload, + CommunicationOrganizationMessageEventPayload, + CommunicationUpdateEventPayload, + CommunicationUserMentionEventPayload, + CommunicationUserMessageEventPayload, CommunityApplicationCreatedEventPayload, - CollaborationDiscussionCommentEventPayload, - PlatformForumDiscussionCommentEventPayload, CommunityInvitationCreatedEventPayload, - CollaborationWhiteboardCreatedEventPayload, - CommentReplyEventPayload, - BaseEventPayload, + CommunityInvitationVirtualContributorCreatedEventPayload, + CommunityNewMemberPayload, + CommunityPlatformInvitationCreatedEventPayload, ContributorPayload, - SpaceBaseEventPayload, + PlatformForumDiscussionCommentEventPayload, + PlatformForumDiscussionCreatedEventPayload, PlatformGlobalRoleChangeEventPayload, + PlatformUserRegistrationEventPayload, + PlatformUserRemovedEventPayload, RoleChangeType, - CommunityPlatformInvitationCreatedEventPayload, - CommunityInvitationVirtualContributorCreatedEventPayload, + SpaceBaseEventPayload, SpaceCreatedEventPayload, } from '@alkemio/notifications-lib'; import { ICallout } from '@domain/collaboration/callout/callout.interface'; @@ -776,9 +776,6 @@ export class NotificationPayloadBuilder { } private getPlatformURL(): string { - const endpoint = this.configService.get( - ConfigurationTypes.HOSTING - )?.endpoint_cluster; - return endpoint; + return this.configService.get('hosting.endpoint_cluster', { infer: true }); } } diff --git a/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts b/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts index 30c9ba70da..e0c609b2c5 100644 --- a/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts +++ b/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts @@ -1,4 +1,4 @@ -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { SsiSovrhdApiException } from '@common/exceptions/ssi.sovrhd.api.exception'; import { SsiSovrhdCredentialRequestFailure } from '@common/exceptions/ssi.sovrhd.credential.request.failure'; import { SsiSovrhdCredentialTypeNotFoundException } from '@common/exceptions/ssi.sovrhd.credential.type.not.found.exception'; @@ -31,8 +31,7 @@ export class SsiSovrhdAdapter { private configService: ConfigService, private httpService: HttpService ) { - const sovrhdConfig = this.configService.get(ConfigurationTypes.SSI)?.issuers - ?.sovrhd; + const sovrhdConfig = this.configService.get('ssi.issuers.sovrhd', { infer: true }); this.sovrhdApiEndpoint = sovrhdConfig.endpoint; this.credentialTypesMap = new Map(); diff --git a/src/services/adapters/storage/ipfs/ipfs.module.ts b/src/services/adapters/storage/ipfs/ipfs.module.ts deleted file mode 100644 index 49be89afcc..0000000000 --- a/src/services/adapters/storage/ipfs/ipfs.module.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Module } from '@nestjs/common'; -import { IpfsService } from './ipfs.service'; - -@Module({ - providers: [IpfsService], - exports: [IpfsService], -}) -export class IpfsModule {} diff --git a/src/services/adapters/storage/ipfs/ipfs.service._spec.ts b/src/services/adapters/storage/ipfs/ipfs.service._spec.ts deleted file mode 100644 index 186768b409..0000000000 --- a/src/services/adapters/storage/ipfs/ipfs.service._spec.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Test, TestingModule } from '@nestjs/testing'; -import { IpfsService } from './ipfs.service'; -import { MockCacheManager } from '@test/mocks/cache-manager.mock'; -import { MockWinstonProvider } from '@test/mocks/winston.provider.mock'; -import { defaultMockerFactory } from '@test/utils/default.mocker.factory'; -import { MockConfigService } from '@test/mocks/config.service.mock'; - -describe('IpfsService', () => { - let service: IpfsService; - - beforeEach(async () => { - const module: TestingModule = await Test.createTestingModule({ - providers: [ - IpfsService, - MockCacheManager, - MockWinstonProvider, - MockConfigService, - ], - }) - .useMocker(defaultMockerFactory) - .compile(); - - service = module.get(IpfsService); - }); - - it('should be defined', () => { - expect(service).toBeDefined(); - }); -}); diff --git a/src/services/adapters/storage/ipfs/ipfs.service.ts b/src/services/adapters/storage/ipfs/ipfs.service.ts deleted file mode 100644 index eef093771c..0000000000 --- a/src/services/adapters/storage/ipfs/ipfs.service.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { ConfigurationTypes, LogContext } from '@common/enums'; -import { streamToBuffer } from '@common/utils'; -import { Inject, Injectable, LoggerService } from '@nestjs/common'; -import { ConfigService } from '@nestjs/config'; -import { ReadStream } from 'fs'; -import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore -import { CID, create, IPFSHTTPClient } from 'ipfs-http-client'; -import { IpfsDeleteFailedException } from '@common/exceptions/ipfs/ipfs.delete.exception'; -import { IpfsGCFailedException } from '@common/exceptions/ipfs/ipfs.gc.exception'; -import { AlkemioConfig } from '@src/types'; - -@Injectable() -export class IpfsService { - private readonly ipfsClient: IPFSHTTPClient; - private readonly ipfsClientEndpoint; - - constructor( - private configService: ConfigService, - @Inject(WINSTON_MODULE_NEST_PROVIDER) - private readonly logger: LoggerService - ) { - const ipfsEndpoint = this.configService.get(ConfigurationTypes.STORAGE) - ?.ipfs?.endpoint; - this.ipfsClientEndpoint = this.configService.get( - ConfigurationTypes.STORAGE - )?.ipfs?.client_endpoint; - const timeout = this.configService.get(ConfigurationTypes.STORAGE)?.ipfs - ?.timeout; - this.ipfsClient = create({ url: ipfsEndpoint, timeout }); - } - - public async uploadFileFromStream(stream: ReadStream): Promise { - const buffer = await streamToBuffer(stream); - return await this.uploadFileFromBuffer(buffer); - } - - public async uploadFileFromBuffer(buffer: Buffer): Promise { - const CID = await this.uploadFileFromBufferCID(buffer); - return this.createIpfsClientEndPoint(CID); - } - - // returns the CID only - public async uploadFileFromBufferCID(buffer: Buffer): Promise { - const res = await this.ipfsClient.add(buffer, { pin: true }); - this.logger.verbose?.( - `Uploaded file with CID: ${res.path}`, - LogContext.IPFS - ); - return res.path; - } - - public getFileContents(CID: string): AsyncIterable | never { - return this.ipfsClient.cat(CID); - } - - private async cidExists(cidID: string): Promise { - try { - const cidObj = CID.parse(cidID); - await this.ipfsClient.dag.get(cidObj, { timeout: 100 }); - return true; - } catch (error: any) { - this.logger.error( - `IPFS file with CID: ${cidID} does not exist in this IPFS instance!`, - error?.stack, - LogContext.IPFS - ); - } - - return false; - } - - public async getBufferByCID(CID: string): Promise { - const chunks = []; - - const exists = await this.cidExists(CID); - if (!exists) return null; - for await (const chunk of this.ipfsClient.cat(CID)) { - chunks.push(chunk); - } - return Buffer.concat(chunks); - } - - public createIpfsClientEndPoint(CID: string): string { - return `${this.ipfsClientEndpoint}/${CID}`; - } - - public unpinFile(CID: string): Promise { - this.logger.verbose?.(`Unpinning file from CID: ${CID}`, LogContext.IPFS); - - try { - return this.ipfsClient.pin.rm(CID); - } catch (error: any) { - this.logger.error('Unpinning failed', error?.stack, LogContext.IPFS); - throw new IpfsDeleteFailedException(`Unpinning failed ${error.message}`); - } - } - - public async garbageCollect(): Promise { - this.logger.verbose?.('Garbage collection started!', LogContext.IPFS); - try { - for await (const gcFile of this.ipfsClient.repo.gc()) { - this.logger.verbose?.( - `Garbage collected ${gcFile.cid}`, - LogContext.IPFS - ); - - if (gcFile.err) { - this.logger.error( - `Error in collection ${gcFile.err}`, - gcFile.err.stack, - LogContext.IPFS - ); - } - } - } catch (error: any) { - this.logger.error( - 'Garbage collection failed', - error?.stack, - LogContext.IPFS - ); - throw new IpfsGCFailedException( - `Garbage collection failed ${error.message}` - ); - } - return true; - } -} diff --git a/src/services/adapters/storage/local-storage/local.storage.adapter.ts b/src/services/adapters/storage/local-storage/local.storage.adapter.ts index f4560fcb16..647acdc67d 100644 --- a/src/services/adapters/storage/local-storage/local.storage.adapter.ts +++ b/src/services/adapters/storage/local-storage/local.storage.adapter.ts @@ -4,7 +4,7 @@ import { ConfigService } from '@nestjs/config'; import { promisify } from 'util'; import { readFile, unlink, writeFile, existsSync, mkdirSync } from 'fs'; import { LocalStorageSaveFailedException } from '@common/exceptions/storage/local-storage/local.storage.save.failed.exception'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { calculateBufferHash, pathResolve } from '@common/utils'; import { LocalStorageDeleteFailedException, @@ -23,8 +23,7 @@ export class LocalStorageAdapter implements StorageService { private readonly storagePath: string; constructor(private configService: ConfigService) { - const pathFromConfig = this.configService.get(ConfigurationTypes.STORAGE) - ?.local_storage?.path; + const pathFromConfig = this.configService.get('storage.local_storage.path', { infer: true }); this.storagePath = pathResolve(pathFromConfig); this.ensureStoragePathExists(); } diff --git a/src/services/ai-server/ai-server/ai.server.resolver.mutations.ts b/src/services/ai-server/ai-server/ai.server.resolver.mutations.ts index 8e2f7dc5a2..ab11d653a9 100644 --- a/src/services/ai-server/ai-server/ai.server.resolver.mutations.ts +++ b/src/services/ai-server/ai-server/ai.server.resolver.mutations.ts @@ -12,7 +12,6 @@ import { AiPersonaServiceService } from '../ai-persona-service/ai.persona.servic import { AiPersonaServiceAuthorizationService } from '../ai-persona-service/ai.persona.service.authorization'; import { CreateAiPersonaServiceInput } from '../ai-persona-service/dto/ai.persona.service.dto.create'; import { IAiPersonaService } from '../ai-persona-service/ai.persona.service.interface'; -import { ConfigurationTypes } from '@common/enums'; import { Space } from '@domain/space/space/space.entity'; import { ChromaClient } from 'chromadb'; import { ConfigService } from '@nestjs/config'; @@ -20,6 +19,7 @@ import { InjectEntityManager } from '@nestjs/typeorm'; import { PlatformAuthorizationPolicyService } from '@platform/authorization/platform.authorization.policy.service'; import { EntityManager } from 'typeorm'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; +import { AlkemioConfig } from '@src/types'; @ObjectType('MigrateEmbeddings') class IMigrateEmbeddingsResponse { @@ -38,7 +38,7 @@ export class AiServerResolverMutations { private platformAuthorizationService: PlatformAuthorizationPolicyService, @InjectEntityManager('default') private entityManager: EntityManager, - private config: ConfigService, + private config: ConfigService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private logger: LoggerService ) {} @@ -60,7 +60,7 @@ export class AiServerResolverMutations { 'User not authenticated to migrate embeddings' ); - const vectorDb = this.config.get(ConfigurationTypes.PLATFORM).vector_db; + const vectorDb = this.config.get('platform.vector_db', { infer: true }); const chroma = new ChromaClient({ path: `http://${vectorDb.host}:${vectorDb.port}`, diff --git a/src/services/ai-server/ai-server/ai.server.service.ts b/src/services/ai-server/ai-server/ai.server.service.ts index 801023d1bb..92a058b439 100644 --- a/src/services/ai-server/ai-server/ai.server.service.ts +++ b/src/services/ai-server/ai-server/ai.server.service.ts @@ -24,7 +24,6 @@ import { import { EventBus } from '@nestjs/cqrs'; import { ConfigService } from '@nestjs/config'; import { ChromaClient } from 'chromadb'; -import { ConfigurationTypes } from '@common/enums/configuration.type'; import { IMessageAnswerToQuestion } from '@domain/communication/message.answer.to.question/message.answer.to.question.interface'; import { VcInteractionService } from '@domain/communication/vc-interaction/vc.interaction.service'; import { CommunicationAdapter } from '@services/adapters/communication-adapter/communication.adapter'; @@ -32,6 +31,7 @@ import { InteractionMessage, MessageSenderRole, } from '../ai-persona-service/dto/interaction.message'; +import { AlkemioConfig } from '@src/types'; @Injectable() export class AiServerService { @@ -40,7 +40,7 @@ export class AiServerService { private aiPersonaEngineAdapter: AiPersonaEngineAdapter, private vcInteractionService: VcInteractionService, private communicationAdapter: CommunicationAdapter, - private config: ConfigService, + private config: ConfigService, @InjectRepository(AiServer) private aiServerRepository: Repository, @Inject(WINSTON_MODULE_NEST_PROVIDER) @@ -153,9 +153,7 @@ export class AiServerService { } private async isContextLoaded(contextID: string): Promise { - const { host, port } = this.config.get( - ConfigurationTypes.PLATFORM - ).vector_db; + const { host, port } = this.config.get('platform.vector_db', { infer: true }); const chroma = new ChromaClient({ path: `http://${host}:${port}` }); const name = this.getContextCollectionID(contextID); diff --git a/src/services/api/chat-guidance/chat.guidance.service.ts b/src/services/api/chat-guidance/chat.guidance.service.ts index 5345b4361d..4d02977556 100644 --- a/src/services/api/chat-guidance/chat.guidance.service.ts +++ b/src/services/api/chat-guidance/chat.guidance.service.ts @@ -1,7 +1,6 @@ import { Inject, LoggerService } from '@nestjs/common'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { AgentInfo } from '@core/authentication.agent.info/agent.info'; -import { ConfigurationTypes } from '@common/enums/configuration.type'; import { ConfigService } from '@nestjs/config'; import { GuidanceEngineAdapter } from '@services/adapters/chat-guidance-adapter/guidance.engine.adapter'; import { ChatGuidanceInput } from './dto/chat.guidance.dto.input'; @@ -41,9 +40,6 @@ export class ChatGuidanceService { } public isGuidanceEngineEnabled(): boolean { - const result = this.configService.get(ConfigurationTypes.PLATFORM) - .guidance_engine?.enabled; - - return Boolean(result); + return this.configService.get('platform.guidance_engine.enabled', { infer: true }) } } diff --git a/src/services/api/search/v1/search.resolver.queries.ts b/src/services/api/search/v1/search.resolver.queries.ts index f2144ad0d0..88155db31b 100644 --- a/src/services/api/search/v1/search.resolver.queries.ts +++ b/src/services/api/search/v1/search.resolver.queries.ts @@ -8,7 +8,6 @@ import { ISearchResults } from '@services/api/search/dto/search.result.dto'; import { SearchService } from './search.service'; import { Search2Service } from '@services/api/search/v2/search2.service'; import { ConfigService } from '@nestjs/config'; -import { ConfigurationTypes } from '@common/enums'; import { AlkemioConfig } from '@src/types'; @Resolver() export class SearchResolverQueries { @@ -18,9 +17,7 @@ export class SearchResolverQueries { private searchService: SearchService, private search2Service: Search2Service ) { - this.useNewSearch = this.configService.get( - ConfigurationTypes.SEARCH - )?.use_new; + this.useNewSearch = this.configService.get('search.use_new', { infer: true }); } @UseGuards(GraphqlGuard) diff --git a/src/services/api/search/v2/extract/search.extract.service.ts b/src/services/api/search/v2/extract/search.extract.service.ts index 0b907ee639..35d8dd0d5c 100644 --- a/src/services/api/search/v2/extract/search.extract.service.ts +++ b/src/services/api/search/v2/extract/search.extract.service.ts @@ -7,7 +7,6 @@ import { ELASTICSEARCH_CLIENT_PROVIDER } from '@constants/index'; import { IBaseAlkemio } from '@domain/common/entity/base-entity'; import { AlkemioErrorStatus, - ConfigurationTypes, LogContext, } from '@common/enums'; import { BaseException } from '@common/exceptions/base.exception'; @@ -17,6 +16,7 @@ import { functionScoreFunctions } from './function.score.functions'; import { buildSearchQuery } from './build.search.query'; import { SearchEntityTypes } from '../../search.entity.types'; import { AlkemioConfig } from '@src/types'; +import { getIndexPattern } from '@services/api/search/v2/ingest/get.index.pattern'; type SearchEntityTypesPublic = | SearchEntityTypes.SPACE @@ -44,7 +44,6 @@ const TYPE_TO_PUBLIC_INDEX = ( }); const DEFAULT_MAX_RESULTS = 25; -const DEFAULT_INDEX_PATTERN = 'alkemio-data-'; @Injectable() export class SearchExtractService { @@ -57,11 +56,9 @@ export class SearchExtractService { @Inject(WINSTON_MODULE_NEST_PROVIDER) private logger: LoggerService, private configService: ConfigService ) { - this.indexPattern = - this.configService.get(ConfigurationTypes.SEARCH)?.index_pattern ?? - DEFAULT_INDEX_PATTERN; + this.indexPattern = getIndexPattern(this.configService); this.maxResults = - this.configService.get(ConfigurationTypes.SEARCH)?.max_results ?? + this.configService.get('search.max_results', { infer: true }) ?? DEFAULT_MAX_RESULTS; if (!client) { diff --git a/src/services/api/search/v2/ingest/get.index.pattern.ts b/src/services/api/search/v2/ingest/get.index.pattern.ts index b119205431..ec712cab33 100644 --- a/src/services/api/search/v2/ingest/get.index.pattern.ts +++ b/src/services/api/search/v2/ingest/get.index.pattern.ts @@ -1,5 +1,4 @@ import { ConfigService } from '@nestjs/config'; -import { ConfigurationTypes } from '@common/enums'; import { AlkemioConfig } from '@src/types'; const DEFAULT_INDEX_PATTERN = 'alkemio-data-'; @@ -7,11 +6,6 @@ const DEFAULT_INDEX_PATTERN = 'alkemio-data-'; export const getIndexPattern = ( configService: ConfigService ) => { - const pattern = - configService.get(ConfigurationTypes.SEARCH)?.index_pattern ?? + return configService.get('search.index_pattern', { infer: true }) ?? DEFAULT_INDEX_PATTERN; - const prefix = - configService.get(ConfigurationTypes.SEARCH)?.index_pattern_prefix ?? ''; - - return `${prefix}${pattern}`; }; diff --git a/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts b/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts index 0baf4a5bbf..b82129b507 100644 --- a/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts +++ b/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts @@ -4,7 +4,7 @@ import { Client as ElasticClient } from '@elastic/elasticsearch'; import { WriteResponseBase } from '@elastic/elasticsearch/lib/api/types'; import { ConfigService } from '@nestjs/config'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { isElasticError, isElasticResponseError } from '../utils'; import { AuthorDetails, @@ -29,13 +29,9 @@ export class ContributionReporterService { @Inject(ELASTICSEARCH_CLIENT_PROVIDER) private readonly client: ElasticClient | undefined ) { - const elasticsearch = this.configService.get( - ConfigurationTypes.INTEGRATIONS - )?.elasticsearch; + const elasticsearch = this.configService.get('integrations.elasticsearch', { infer: true }); - this.environment = this.configService.get( - ConfigurationTypes.HOSTING - )?.environment; + this.environment = this.configService.get('hosting.environment', { infer: true }); this.activityIndexName = elasticsearch?.indices?.contribution; } diff --git a/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts b/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts index c8107e2c7e..17154118e7 100644 --- a/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts +++ b/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts @@ -1,7 +1,6 @@ import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { Client } from '@elastic/elasticsearch'; -import { ConfigurationTypes } from '@common/enums'; import fs from 'fs'; import { AlkemioConfig } from '@src/types'; @@ -9,9 +8,7 @@ export const elasticSearchClientFactory = async ( logger: LoggerService, configService: ConfigService ): Promise => { - const elasticsearch = configService.get( - ConfigurationTypes.INTEGRATIONS - )?.elasticsearch; + const elasticsearch = configService.get('integrations.elasticsearch', { infer: true }); const { host, retries, timeout, api_key, tls } = elasticsearch; const rejectUnauthorized = tls.rejectUnauthorized ?? false; diff --git a/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts b/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts index 5c68928a86..11e579aefd 100644 --- a/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts +++ b/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts @@ -4,7 +4,7 @@ import { Client as ElasticClient } from '@elastic/elasticsearch'; import { WriteResponseBase } from '@elastic/elasticsearch/lib/api/types'; import { ConfigService } from '@nestjs/config'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { ELASTICSEARCH_CLIENT_PROVIDER } from '@constants/index'; import { isElasticError, isElasticResponseError } from '../utils'; import { GuidanceUsage } from './guidance.usage'; @@ -34,13 +34,9 @@ export class GuidanceReporterService { LogContext.CHAT_GUIDANCE_REPORTER ); } - const elasticsearch = this.configService.get( - ConfigurationTypes.INTEGRATIONS - )?.elasticsearch; + const elasticsearch = this.configService.get('integrations.elasticsearch', { infer: true }); - this.environment = this.configService.get( - ConfigurationTypes.HOSTING - )?.environment; + this.environment = this.configService.get('hosting.environment', { infer: true }); this.indexName = elasticsearch?.indices?.guidance_usage; } diff --git a/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts b/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts index a64a921442..b6d7b90ab8 100644 --- a/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts +++ b/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts @@ -3,7 +3,7 @@ import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { ConfigService } from '@nestjs/config'; import { ELASTICSEARCH_CLIENT_PROVIDER } from '@common/constants'; import { Client as ElasticClient } from '@elastic/elasticsearch'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { NamingDocument } from './types'; import { handleElasticError } from '@services/external/elasticsearch/utils/handle.elastic.error'; import { AlkemioConfig } from '@src/types'; @@ -21,13 +21,9 @@ export class NameReporterService { @Inject(ELASTICSEARCH_CLIENT_PROVIDER) private readonly client: ElasticClient | undefined ) { - const elasticsearch = this.configService.get( - ConfigurationTypes.INTEGRATIONS - )?.elasticsearch; + const elasticsearch = this.configService.get('integrations.elasticsearch', { infer: true }); - this.environment = this.configService.get( - ConfigurationTypes.HOSTING - )?.environment; + this.environment = this.configService.get('hosting.environment', { infer: true }); const { indices, policies } = elasticsearch; this.indexName = indices?.namings; diff --git a/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts b/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts index d80ecbd958..2d512cf07d 100644 --- a/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts +++ b/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts @@ -5,7 +5,6 @@ import { ConfigService } from '@nestjs/config'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { AlkemioErrorStatus, - ConfigurationTypes, LogContext, } from '@common/enums'; import { BaseException } from '@common/exceptions/base.exception'; @@ -38,7 +37,7 @@ const factory = async ( logger: LoggerService, configService: ConfigService ) => { - const { host, port } = configService.get(ConfigurationTypes.STORAGE).redis; + const { host, port } = configService.get('storage.redis', { infer: true }); if (!host) { throw new BaseException( diff --git a/src/services/external/excalidraw-backend/excalidraw.server.ts b/src/services/external/excalidraw-backend/excalidraw.server.ts index 46e346f5e4..3e9d0302fc 100644 --- a/src/services/external/excalidraw-backend/excalidraw.server.ts +++ b/src/services/external/excalidraw-backend/excalidraw.server.ts @@ -9,7 +9,7 @@ import { UnauthorizedException, } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { APP_ID, EXCALIDRAW_SERVER, UUID_LENGTH } from '@common/constants'; import { arrayRandomElement } from '@common/utils'; import { AuthenticationService } from '@core/authentication/authentication.service'; @@ -100,7 +100,7 @@ export class ExcalidrawServer { save_timeout, collaborator_mode_timeout, max_collaborators_in_room, - } = this.configService.get(ConfigurationTypes.COLLABORATION)?.whiteboards; + } = this.configService.get('collaboration.whiteboards', { infer: true }); this.contributionWindowMs = (contribution_window ?? defaultContributionInterval) * 1000; @@ -128,9 +128,7 @@ export class ExcalidrawServer { } private async init() { - const kratosPublicBaseUrl = this.configService.get( - ConfigurationTypes.IDENTITY - ).authentication.providers.ory.kratos_public_base_url_server; + const kratosPublicBaseUrl = this.configService.get('identity.authentication.providers.ory.kratos_public_base_url_server', { infer: true }); const kratosClient = new FrontendApi( new Configuration({ diff --git a/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts b/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts index 3aaba60085..c89b2365ea 100644 --- a/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts +++ b/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts @@ -5,7 +5,6 @@ import { ConfigService } from '@nestjs/config'; import { LoggerService } from '@nestjs/common'; import { AlkemioErrorStatus, - ConfigurationTypes, LogContext, } from '@common/enums'; import { BaseException } from '@common/exceptions/base.exception'; @@ -17,7 +16,7 @@ export const getExcalidrawBaseServerOrFail = ( logger: LoggerService, adapterFactory?: typeof Adapter | ((nsp: Namespace) => Adapter) ): SocketIoServer | never => { - const port = configService.get(ConfigurationTypes.HOSTING).whiteboard_rt.port; + const port = configService.get('hosting.whiteboard_rt.port', { infer: true }); if (!port) { throw new BaseException( diff --git a/src/types/alkemio.config.ts b/src/types/alkemio.config.ts index 8b53c3d558..4a20c87885 100644 --- a/src/types/alkemio.config.ts +++ b/src/types/alkemio.config.ts @@ -145,6 +145,7 @@ export type AlkemioConfig = { guidance_usage: string; }; tls: { + ca_cert_path: string | 'none'; rejectUnauthorized: boolean; }; policies: { @@ -192,6 +193,10 @@ export type AlkemioConfig = { guidance_engine: { enabled: boolean; }; + vector_db: { + host: string; + port: number; + } }; ssi: { enabled: boolean; From ea20ce77c55ac2ea01d2fbfca15b274f190c8fcb Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Fri, 2 Aug 2024 11:02:06 +0300 Subject: [PATCH 11/27] wip --- alkemio.yml | 3 + src/common/utils/replace.regex.ts | 72 ----------- src/config/winston.config.ts | 17 +-- .../agent.info.cache.service.ts | 8 +- .../authentication/authentication.service.ts | 41 +++---- src/core/authentication/ory.strategy.ts | 8 +- src/core/bootstrap/bootstrap.service.ts | 47 ++------ ...ngine.community.manager.service.factory.ts | 7 +- src/main.ts | 4 +- .../configuration/config/config.service.ts | 112 +++++++----------- src/types/alkemio.config.ts | 5 + 11 files changed, 87 insertions(+), 237 deletions(-) delete mode 100644 src/common/utils/replace.regex.ts diff --git a/alkemio.yml b/alkemio.yml index 35743110cb..fcc9644c20 100644 --- a/alkemio.yml +++ b/alkemio.yml @@ -278,6 +278,9 @@ communications: ## storage ## # Alkemio uses multiple types of persistent storage, including SQL database and IPFS. storage: + graphql_upload: + # 20MB + max_file_size: 1048576 # MySQL database configuration for usage by the Alkemio Server. # The authentication method used by Alkemio Server is MySQL Native Password. # Note: both schema / database name are used for configuration and they need to have the same value. diff --git a/src/common/utils/replace.regex.ts b/src/common/utils/replace.regex.ts deleted file mode 100644 index b64c0134f3..0000000000 --- a/src/common/utils/replace.regex.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { AgentInfo } from '@core/authentication.agent.info/agent.info'; -import { BaseAlkemioEntity } from '@domain/common/entity/base-entity'; -import { StorageBucketService } from '@domain/storage/storage-bucket/storage.bucket.service'; -import { IpfsService } from '@services/adapters/storage/ipfs/ipfs.service'; -import { StorageAggregatorResolverService } from '@services/infrastructure/storage-aggregator-resolver/storage.aggregator.resolver.service'; -import { EntityManager, ObjectType } from 'typeorm'; - -type ReplacementCallback = ( - entityManager: EntityManager, - entityClass: ObjectType, - ipfsService: IpfsService, - storageBucketService: StorageBucketService, - storageAggregatorResolverService: StorageAggregatorResolverService, - agentInfo: AgentInfo, - regex: RegExp, - matchedText: string, - row: any, - anonymousReadAccess: boolean -) => Promise; - -export async function replaceRegex( - entityManager: EntityManager, - entityClass: ObjectType, - ipfsService: IpfsService, - storageBucketService: StorageBucketService, - storageAggregatorResolverService: StorageAggregatorResolverService, - agentInfo: AgentInfo, - columnName: string, - regex: string, - anonymousReadAccess: boolean, - replacementCallback: ReplacementCallback -): Promise { - const queryBuilder = entityManager.connection - .getRepository(entityClass) - .createQueryBuilder(); - const escapedColumn = queryBuilder.escape(columnName); - // Fetch all rows with the matching regex - const rows = await queryBuilder - .select() - .where(`${columnName} REGEXP :regex`) - .setParameters({ regex }) - .getMany(); - - // Update each row with the replaced text - for (const row of rows) { - try { - const regExp = new RegExp(regex); - const matchedText = (row as any)[columnName].match(regExp)[0]; - const replacementText = await replacementCallback( - entityManager, - entityClass, - ipfsService, - storageBucketService, - storageAggregatorResolverService, - agentInfo, - regExp, - matchedText, - row, - anonymousReadAccess - ); - await queryBuilder - .update(entityClass) - .set({ - [columnName]: () => - `REGEXP_REPLACE(${escapedColumn}, :regex, :replacementText)`, - } as any) - .setParameters({ regex, replacementText }) - .where('id = :id', { id: row.id }) - .execute(); - } catch (error) {} - } -} diff --git a/src/config/winston.config.ts b/src/config/winston.config.ts index e2fcc43813..f5e24b6ea8 100644 --- a/src/config/winston.config.ts +++ b/src/config/winston.config.ts @@ -2,7 +2,6 @@ import { Injectable } from '@nestjs/common'; import * as winston from 'winston'; import { utilities as nestWinstonModuleUtilities } from 'nest-winston'; import { ConfigService } from '@nestjs/config'; -import { ConfigurationTypes } from '@common/enums'; import { FileTransportOptions } from 'winston/lib/winston/transports'; import * as logform from 'logform'; import { AlkemioConfig } from '@src/types'; @@ -28,28 +27,23 @@ export class WinstonConfigService { constructor(private configService: ConfigService) {} async createWinstonModuleOptions() { - const consoleEnabled: boolean = this.configService.get( - ConfigurationTypes.MONITORING - )?.logging?.console_logging_enabled; + const consoleEnabled: boolean = this.configService.get('monitoring.logging.console_logging_enabled', { infer: true }); const transports: any[] = [ new winston.transports.Console({ format: winston.format.combine( - ...(this.configService.get(ConfigurationTypes.MONITORING)?.logging + ...(this.configService.get('monitoring.logging', { infer: true }) ?.json ? consoleLoggingProdFormat : consoleLoggingStandardFormat) ), level: this.configService - .get(ConfigurationTypes.MONITORING) - ?.logging?.level.toLowerCase(), + .get('monitoring.logging.level', { infer: true }).toLowerCase(), silent: !consoleEnabled, }), ]; - const contextToFileConfig = this.configService.get( - ConfigurationTypes.MONITORING - )?.logging.context_to_file; + const contextToFileConfig = this.configService.get('monitoring.logging.context_to_file', { infer: true }); if (contextToFileConfig.enabled) { const filename = contextToFileConfig.filename; @@ -84,8 +78,7 @@ export class WinstonConfigService { const fileTransportOptions: FileTransportOptions = { format: myFormat, level: this.configService - .get(ConfigurationTypes.MONITORING) - ?.logging?.level.toLowerCase(), + .get('monitoring.logging.level', { infer: true }).toLowerCase(), silent: false, filename: filename, }; diff --git a/src/core/authentication.agent.info/agent.info.cache.service.ts b/src/core/authentication.agent.info/agent.info.cache.service.ts index 8e3d298c0c..f06039a3a6 100644 --- a/src/core/authentication.agent.info/agent.info.cache.service.ts +++ b/src/core/authentication.agent.info/agent.info.cache.service.ts @@ -1,5 +1,3 @@ -// import { REDIS_LOCK_SERVICE } from '@common/constants'; -import { ConfigurationTypes } from '@common/enums/configuration.type'; import { LogContext } from '@common/enums/logging.context'; import { AgentInfo } from './agent.info'; import { Inject, Injectable, LoggerService } from '@nestjs/common'; @@ -8,7 +6,7 @@ import { ConfigService } from '@nestjs/config'; import { InjectEntityManager } from '@nestjs/typeorm'; import { Cache } from 'cache-manager'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; -// import Redlock, { RedlockAbortSignal } from 'redlock'; + import { EntityManager } from 'typeorm'; import { IAgent, ICredential } from '../../domain/agent'; import { AlkemioConfig } from '@src/types'; @@ -27,9 +25,7 @@ export class AgentInfoCacheService { @InjectEntityManager('default') private entityManager: EntityManager ) { - this.cache_ttl = this.configService.get( - ConfigurationTypes.IDENTITY - ).authentication.cache_ttl; + this.cache_ttl = this.configService.get('identity.authentication.cache_ttl', { infer: true }); } public async getAgentInfoFromCache( diff --git a/src/core/authentication/authentication.service.ts b/src/core/authentication/authentication.service.ts index 45859a4569..cea569b80a 100644 --- a/src/core/authentication/authentication.service.ts +++ b/src/core/authentication/authentication.service.ts @@ -1,12 +1,7 @@ import { ConfigService } from '@nestjs/config'; import { Inject, Injectable, LoggerService } from '@nestjs/common'; -import { - Configuration, - FrontendApi, - IdentityApi, - Session, -} from '@ory/kratos-client'; -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { Configuration, FrontendApi, IdentityApi, Session } from '@ory/kratos-client'; +import { LogContext } from '@common/enums'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { UserService } from '@domain/community/user/user.service'; import { AgentInfo } from '../authentication.agent.info/agent.info'; @@ -37,26 +32,20 @@ export class AuthenticationService { private agentService: AgentService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { - this.kratosPublicUrlServer = this.configService.get( - ConfigurationTypes.IDENTITY - ).authentication.providers.ory.kratos_public_base_url_server; - const kratosAdminUrlServer = this.configService.get( - ConfigurationTypes.IDENTITY - ).authentication.providers.ory.kratos_admin_base_url_server; - - this.adminPasswordIdentifier = this.configService.get( - ConfigurationTypes.IDENTITY - ).authentication.providers.ory.admin_service_account.username; - this.adminPassword = this.configService.get( - ConfigurationTypes.IDENTITY - ).authentication.providers.ory.admin_service_account.password; - - const earliestPossibleExtend = this.configService.get( - ConfigurationTypes.IDENTITY - ).authentication.providers.ory.earliest_possible_extend; + const { + kratos_public_base_url_server, + kratos_admin_base_url_server, + admin_service_account, + earliest_possible_extend + } = this.configService.get('identity.authentication.providers.ory', { infer: true }); + this.kratosPublicUrlServer = kratos_public_base_url_server; + const kratosAdminUrlServer = kratos_admin_base_url_server + + this.adminPasswordIdentifier = admin_service_account.username; + this.adminPassword = admin_service_account.password; this.extendSessionMinRemainingTTL = this.parseEarliestPossibleExtend( - earliestPossibleExtend + earliest_possible_extend ); this.kratosIdentityClient = new IdentityApi( @@ -161,7 +150,7 @@ export class AuthenticationService { agentInfo.communicationID = agentInfoMetadata.communicationID; // Store also retrieved verified credentials; todo: likely slow, need to evaluate other options - const ssiEnabled = this.configService.get(ConfigurationTypes.SSI).enabled; + const ssiEnabled = this.configService.get('ssi.enabled', { infer: true }); if (ssiEnabled) { const VCs = await this.agentService.getVerifiedCredentials( diff --git a/src/core/authentication/ory.strategy.ts b/src/core/authentication/ory.strategy.ts index a04c33cf1b..11eae7ac65 100644 --- a/src/core/authentication/ory.strategy.ts +++ b/src/core/authentication/ory.strategy.ts @@ -1,6 +1,5 @@ import { AlkemioErrorStatus, - ConfigurationTypes, LogContext, } from '@common/enums'; import { Inject, Injectable, LoggerService } from '@nestjs/common'; @@ -24,16 +23,15 @@ export class OryStrategy extends PassportStrategy(Strategy, 'oathkeeper-jwt') { private readonly authService: AuthenticationService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { + super({ secretOrKeyProvider: passportJwtSecret({ cache: true, rateLimit: true, jwksRequestsPerMinute: 5, - jwksUri: configService.get(ConfigurationTypes.IDENTITY)?.authentication - ?.providers?.ory?.jwks_uri, + jwksUri: configService.get('identity.authentication.providers.ory.jwks_uri', { infer: true }), }), - issuer: configService.get(ConfigurationTypes.IDENTITY)?.authentication - ?.providers?.ory?.issuer, + issuer: configService.get('identity.authentication.providers.ory.issuer', { infer: true }), jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ignoreExpiration: true, }); diff --git a/src/core/bootstrap/bootstrap.service.ts b/src/core/bootstrap/bootstrap.service.ts index 85d3dff332..cdfb9ead94 100644 --- a/src/core/bootstrap/bootstrap.service.ts +++ b/src/core/bootstrap/bootstrap.service.ts @@ -64,13 +64,12 @@ export class BootstrapService { // this.ingestService.ingest(); // todo remove later try { this.logger.verbose?.('Bootstrapping...', LogContext.BOOTSTRAP); - this.logConfiguration(); Profiling.logger = this.logger; - const profilingEnabled = this.configService.get( - ConfigurationTypes.MONITORING - )?.logging?.profiling_enabled; - if (profilingEnabled) Profiling.profilingEnabled = profilingEnabled; + const profilingEnabled = this.configService.get('monitoring.logging.profiling_enabled', { infer: true }); + if (profilingEnabled) { + Profiling.profilingEnabled = profilingEnabled; + } await this.ensureAccountSpaceSingleton(); await this.bootstrapProfiles(); @@ -89,38 +88,8 @@ export class BootstrapService { } } - logConfiguration() { - this.logger.verbose?.( - '==== Configuration - Start ===', - LogContext.BOOTSTRAP - ); - - const values = Object.values(ConfigurationTypes); - for (const value of values) { - this.logConfigLevel(value, this.configService.get(value)); - } - this.logger.verbose?.('==== Configuration - End ===', LogContext.BOOTSTRAP); - } - - logConfigLevel(key: any, value: any, indent = '', incrementalIndent = ' ') { - if (typeof value === 'object') { - const msg = `${indent}${key}:`; - this.logger.verbose?.(`${msg}`, LogContext.BOOTSTRAP); - Object.keys(value).forEach(childKey => { - const childValue = value[childKey]; - const newIndent = `${indent}${incrementalIndent}`; - this.logConfigLevel(childKey, childValue, newIndent, incrementalIndent); - }); - } else { - const msg = `${indent}==> ${key}: ${value}`; - this.logger.verbose?.(`${msg}`, LogContext.BOOTSTRAP); - } - } - async bootstrapProfiles() { - const bootstrapAuthorizationEnabled = this.configService.get( - ConfigurationTypes.BOOTSTRAP - )?.authorization?.enabled; + const bootstrapAuthorizationEnabled = this.configService.get('bootstrap.authorization.enabled', { infer: true }); if (!bootstrapAuthorizationEnabled) { this.logger.verbose?.( `Authorization Profile Loading: ${bootstrapAuthorizationEnabled}`, @@ -129,9 +98,7 @@ export class BootstrapService { return; } - const bootstrapFilePath = this.configService.get( - ConfigurationTypes.BOOTSTRAP - )?.authorization?.file as string; + const bootstrapFilePath = this.configService.get('bootstrap.authorization.file', { infer: true }); let bootstrapJson = { ...defaultRoles, @@ -233,7 +200,7 @@ export class BootstrapService { } async ensureSsiPopulated() { - const ssiEnabled = this.configService.get(ConfigurationTypes.SSI).enabled; + const ssiEnabled = this.configService.get('ssi.enabled', { infer: true }); if (ssiEnabled) { await this.agentService.ensureDidsCreated(); } diff --git a/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts b/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts index 7ef853bc06..2b33526e98 100644 --- a/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts +++ b/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts @@ -1,4 +1,4 @@ -import { ConfigurationTypes, LogContext } from '@common/enums'; +import { LogContext } from '@common/enums'; import { MessagingQueue } from '@common/enums/messaging.queue'; import { LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; @@ -9,10 +9,7 @@ export async function virtualContributorEngineCommunityManagerServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService.get( - ConfigurationTypes.MICROSERVICES - )?.rabbitmq; - const connectionOptions = rabbitMqOptions.connection; + const connectionOptions = configService.get('microservices.rabbitmq.connection', { infer: true }); const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { const options = { diff --git a/src/main.ts b/src/main.ts index e4cd66b6a5..900925cdef 100644 --- a/src/main.ts +++ b/src/main.ts @@ -56,9 +56,9 @@ const bootstrap = async () => { app.use( graphqlUploadExpress({ - maxFileSize: configService.get(ConfigurationTypes.STORAGE, { + maxFileSize: configService.get('storage.graphql_upload.max_file_size', { infer: true, - })?.file?.max_file_size, // todo: this does not exist in the config + }) }) ); diff --git a/src/platform/configuration/config/config.service.ts b/src/platform/configuration/config/config.service.ts index cea4bd59d6..da99796cf9 100644 --- a/src/platform/configuration/config/config.service.ts +++ b/src/platform/configuration/config/config.service.ts @@ -15,15 +15,9 @@ export class KonfigService { this.configService.get('hosting.endpoint_cluster', { infer: true }) ).hostname; - const sentryConfig = this.configService.get( - ConfigurationTypes.MONITORING - )?.sentry; - const apmConfig = this.configService.get( - ConfigurationTypes.MONITORING - )?.apm; - const geoConfig = this.configService.get( - ConfigurationTypes.INTEGRATIONS - )?.geo; + const { sentry, apm } = this.configService.get('monitoring', { infer: true }); + const geoConfig = this.configService.get('integrations.geo', { infer: true }); + const platform = this.configService.get('platform', { infer: true }); return { authentication: { providers: await this.getAuthenticationProvidersConfig(), @@ -31,87 +25,71 @@ export class KonfigService { featureFlags: [ { name: PlatformFeatureFlagName.SSI, - enabled: this.configService.get(ConfigurationTypes.SSI)?.enabled, + enabled: this.configService.get('ssi.enabled', { infer: true }), }, { name: PlatformFeatureFlagName.COMMUNICATIONS, - enabled: this.configService.get(ConfigurationTypes.COMMUNICATIONS) - ?.enabled, + enabled: this.configService.get('communications.enabled', { infer: true }), }, { name: PlatformFeatureFlagName.COMMUNICATIONS_DISCUSSIONS, - enabled: this.configService.get(ConfigurationTypes.COMMUNICATIONS) - ?.discussions?.enabled, + enabled: this.configService.get('communications.discussions.enabled', { infer: true }), }, { name: PlatformFeatureFlagName.SUBSCRIPTIONS, - enabled: this.configService.get(ConfigurationTypes.HOSTING) - ?.subscriptions?.enabled, + enabled: this.configService.get('hosting.subscriptions.enabled', { infer: true }), }, { name: PlatformFeatureFlagName.NOTIFICATIONS, - enabled: this.configService.get(ConfigurationTypes.NOTIFICATIONS) - ?.enabled, + enabled: this.configService.get('notifications.enabled', { infer: true }), }, { name: PlatformFeatureFlagName.WHITEBOARDS, - enabled: this.configService.get(ConfigurationTypes.COLLABORATION) - ?.whiteboards?.enabled, + enabled: this.configService.get('collaboration.whiteboards.enabled', { infer: true }), }, { name: PlatformFeatureFlagName.LANDING_PAGE, - enabled: this.configService.get(ConfigurationTypes.PLATFORM) - ?.landing_page?.enabled, + enabled: this.configService.get('platform.landing_page.enabled', { infer: true }), }, { name: PlatformFeatureFlagName.GUIDENCE_ENGINE, - enabled: this.configService.get(ConfigurationTypes.PLATFORM) - ?.guidance_engine?.enabled, + enabled: this.configService.get('platform.guidance_engine.enabled', { infer: true }), }, ], locations: { domain, - environment: this.configService.get(ConfigurationTypes.HOSTING) - ?.environment, - terms: this.configService.get(ConfigurationTypes.PLATFORM)?.terms, - privacy: this.configService.get(ConfigurationTypes.PLATFORM)?.privacy, - security: this.configService.get(ConfigurationTypes.PLATFORM)?.security, - support: this.configService.get(ConfigurationTypes.PLATFORM)?.support, - feedback: this.configService.get(ConfigurationTypes.PLATFORM)?.feedback, - forumreleases: this.configService.get(ConfigurationTypes.PLATFORM) - ?.forumreleases, - about: this.configService.get(ConfigurationTypes.PLATFORM)?.about, - landing: this.configService.get(ConfigurationTypes.PLATFORM)?.landing, - blog: this.configService.get(ConfigurationTypes.PLATFORM)?.blog, - impact: this.configService.get(ConfigurationTypes.PLATFORM)?.impact, - inspiration: this.configService.get(ConfigurationTypes.PLATFORM) - ?.inspiration, - innovationLibrary: this.configService.get(ConfigurationTypes.PLATFORM) - ?.innovationLibrary, - foundation: this.configService.get(ConfigurationTypes.PLATFORM) - ?.foundation, - contactsupport: this.configService.get(ConfigurationTypes.PLATFORM) - ?.contactsupport, - switchplan: this.configService.get(ConfigurationTypes.PLATFORM) - ?.switchplan, - opensource: this.configService.get(ConfigurationTypes.PLATFORM) - ?.opensource, - releases: this.configService.get(ConfigurationTypes.PLATFORM)?.releases, - help: this.configService.get(ConfigurationTypes.PLATFORM)?.help, - community: this.configService.get(ConfigurationTypes.PLATFORM) - ?.community, - newuser: this.configService.get(ConfigurationTypes.PLATFORM)?.newuser, - tips: this.configService.get(ConfigurationTypes.PLATFORM)?.tips, - aup: this.configService.get(ConfigurationTypes.PLATFORM)?.aup, + environment: this.configService.get('hosting.environment', { infer: true }), + terms: platform.terms, + privacy: platform.privacy, + security: platform.security, + support: platform.support, + feedback: platform.feedback, + forumreleases: platform.forumreleases, + about: platform.about, + landing: platform.landing, + blog: platform.blog, + impact: platform.impact, + inspiration: platform.inspiration, + innovationLibrary: platform.innovationLibrary, + foundation: platform.foundation, + contactsupport: platform.contactsupport, + switchplan: platform.switchplan, + opensource: platform.opensource, + releases: platform.releases, + help: platform.help, + community: platform.community, + newuser: platform.newuser, + tips: platform.tips, + aup: platform.aup, }, sentry: { - enabled: sentryConfig?.enabled, - endpoint: sentryConfig?.endpoint, - submitPII: sentryConfig?.submit_pii, + enabled: sentry?.enabled, + endpoint: sentry?.endpoint, + submitPII: sentry?.submit_pii, }, apm: { - rumEnabled: apmConfig?.rumEnabled, - endpoint: apmConfig?.endpoint, + rumEnabled: apm?.rumEnabled, + endpoint: apm?.endpoint, }, geo: { endpoint: geoConfig?.rest_endpoint, @@ -122,7 +100,7 @@ export class KonfigService { async getAuthenticationProvidersConfig(): Promise< IAuthenticationProviderConfig[] > { - const authProviders = [ + return [ { name: 'Ory Kratos Config', label: 'Ory Kratos Config', @@ -131,18 +109,14 @@ export class KonfigService { config: await this.getOryConfig(), }, ]; - - return authProviders; } async getOryConfig(): Promise { - const oryConfig = ( - await this.configService.get(ConfigurationTypes.IDENTITY) - )?.authentication?.providers?.ory; - const res = { + const oryConfig = + this.configService.get('identity.authentication.providers.ory', { infer: true }); + return { kratosPublicBaseURL: oryConfig.kratos_public_base_url, issuer: oryConfig.issuer, } as IOryConfig; - return res; } } diff --git a/src/types/alkemio.config.ts b/src/types/alkemio.config.ts index 4a20c87885..d6b45505a9 100644 --- a/src/types/alkemio.config.ts +++ b/src/types/alkemio.config.ts @@ -97,6 +97,9 @@ export type AlkemioConfig = { }; }; storage: { + graphql_upload: { + max_file_size: number; + }, database: { host: string; port: number; @@ -177,6 +180,8 @@ export type AlkemioConfig = { landing: string; blog: string; impact: string; + inspiration: string; + innovationLibrary: string; foundation: string; contactsupport: string; switchplan: string; From 5a7728b04f3b6db6c3a31006a1ec0d1d66033a6d Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Fri, 2 Aug 2024 11:47:08 +0300 Subject: [PATCH 12/27] fixed tests --- .../authentication.service.spec.ts | 16 ++++------ .../authentication/authentication.service.ts | 2 ++ .../geo-location/geo.location.service.spec.ts | 29 ++++++++++++------- .../geo-location/geo.location.service.ts | 2 +- 4 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/core/authentication/authentication.service.spec.ts b/src/core/authentication/authentication.service.spec.ts index a99131c89b..f4087083d6 100644 --- a/src/core/authentication/authentication.service.spec.ts +++ b/src/core/authentication/authentication.service.spec.ts @@ -31,17 +31,11 @@ describe('AuthService', () => { const ConfigServiceMock = { get: jest.fn().mockReturnValue({ - authentication: { - providers: { - ory: { - kratos_public_base_url_server: 'mockUrl', - kratos_admin_base_url_server: 'mockUrl', - admin_service_account: { - username: 'mock', - password: 'mock', - }, - }, - }, + kratos_public_base_url_server: 'mockUrl', + kratos_admin_base_url_server: 'mockUrl', + admin_service_account: { + username: 'mock', + password: 'mock', }, }), }; diff --git a/src/core/authentication/authentication.service.ts b/src/core/authentication/authentication.service.ts index cea569b80a..d11334e32d 100644 --- a/src/core/authentication/authentication.service.ts +++ b/src/core/authentication/authentication.service.ts @@ -25,6 +25,7 @@ export class AuthenticationService { private readonly kratosIdentityClient: IdentityApi; private readonly kratosFrontEndClient: FrontendApi; + constructor( private agentCacheService: AgentInfoCacheService, private configService: ConfigService, @@ -32,6 +33,7 @@ export class AuthenticationService { private agentService: AgentService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { + this.kratosPublicUrlServer = this.configService.get('identity.authentication.providers.ory.kratos_public_base_url_server', { infer: true }); const { kratos_public_base_url_server, kratos_admin_base_url_server, diff --git a/src/services/external/geo-location/geo.location.service.spec.ts b/src/services/external/geo-location/geo.location.service.spec.ts index 077b630f9a..a52a699536 100644 --- a/src/services/external/geo-location/geo.location.service.spec.ts +++ b/src/services/external/geo-location/geo.location.service.spec.ts @@ -26,12 +26,10 @@ describe('GeoLocationService', () => { MockConfigService.useValue = { ...MockConfigService.useValue, get: () => ({ - geo: { - service_endpoint: 'mock', - allowed_calls_to_service: 1, - allowed_calls_to_service_window: 1, - cache_entry_ttl: 14440, - }, + service_endpoint: 'mock', + allowed_calls_to_service: 1, + allowed_calls_to_service_window: 1, + cache_entry_ttl: 1, }), }; @@ -160,12 +158,21 @@ describe('GeoLocationService', () => { // execute const result = await geoLocationService.getGeo('ip'); // assert - expect(spySet).toBeCalledWith( - 'ip', - { latitude: 1, longitude: 2 }, - { ttl: 14440 } - ); expect(spySet).toBeCalledTimes(2); + // incrementCacheMetadata + expect(spySet).toHaveBeenNthCalledWith( + 1, + "geo-service-call-limit", + { start: 1, calls: 1 }, + { ttl: 1 } + ); + // set data in cache + expect(spySet).toHaveBeenNthCalledWith( + 2, + 'ip', + { latitude: 1, longitude: 2 }, + { ttl: 1 }, + ); expect(result).toStrictEqual({ latitude: 1, longitude: 2, diff --git a/src/services/external/geo-location/geo.location.service.ts b/src/services/external/geo-location/geo.location.service.ts index 449fc4c7bd..ae2259df7d 100644 --- a/src/services/external/geo-location/geo.location.service.ts +++ b/src/services/external/geo-location/geo.location.service.ts @@ -33,7 +33,7 @@ export class GeoLocationService { private readonly configService: ConfigService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { - const config = configService.get('integrations.geo', { infer: true }); + const config = this.configService.get('integrations.geo', { infer: true }); this.endpoint = config.service_endpoint; this.allowedCallsToService = config.allowed_calls_to_service; this.allowedCallsToServiceWindow = config.allowed_calls_to_service_window; From ea883d1e56825cb25c9dc0ee2229b28e6c3989c6 Mon Sep 17 00:00:00 2001 From: Neil Smyth Date: Sun, 4 Aug 2024 15:40:22 +0100 Subject: [PATCH 13/27] mentions to switch over to UUID as soon as a mention is detected; remove large amount of usage of nameID in logging messages --- .../post/post.resolver.mutations.ts | 4 +- .../whiteboard.resolver.mutations.ts | 6 +-- .../messaging/mention.interface.ts | 2 +- src/domain/communication/room/room.module.ts | 2 + .../room/room.resolver.mutations.ts | 7 ++- .../room/room.service.mentions.ts | 46 ++++++++++++++----- .../community-role/community.role.service.ts | 4 +- .../organization.role.resolver.fields.ts | 6 +-- .../organization.role.resolver.mutations.ts | 4 +- .../organization.role.service.ts | 2 +- .../organization.resolver.fields.ts | 6 +-- .../organization.resolver.mutations.ts | 8 ++-- .../organization/organization.service.ts | 8 ++-- src/domain/community/user/user.service.ts | 6 +-- .../virtual.contributor.resolver.fields.ts | 2 +- .../virtual.contributor.resolver.mutations.ts | 6 +-- .../virtual.contributor.service.ts | 6 +-- .../account/account.resolver.mutations.ts | 10 ++-- .../space/space/space.resolver.mutations.ts | 6 +-- src/domain/space/space/space.service.ts | 2 +- .../storage.aggregator.service.ts | 20 ++++---- .../event/event.resolver.mutations.ts | 4 +- .../innovation.pack.resolver.mutations.ts | 4 +- .../innovation-pack/innovaton.pack.service.ts | 2 +- .../platform.settings.resolver.mutations.ts | 2 +- .../activity-adapter/activity.adapter.ts | 7 ++- .../notification.adapter.ts | 2 +- .../notification.payload.builder.ts | 19 +++----- .../conversion.resolver.mutations.ts | 2 +- .../api/conversion/conversion.service.ts | 16 +++---- .../api/lookup/lookup.resolver.fields.ts | 2 +- .../api/registration/registration.service.ts | 6 +-- ...pace.roles.for.contributor.query.result.ts | 6 +-- .../v1/search.result.builder.service.ts | 6 +-- .../contributor.lookup.service.ts | 22 ++++++++- 35 files changed, 146 insertions(+), 117 deletions(-) diff --git a/src/domain/collaboration/post/post.resolver.mutations.ts b/src/domain/collaboration/post/post.resolver.mutations.ts index b01efeece5..6eb4d80065 100644 --- a/src/domain/collaboration/post/post.resolver.mutations.ts +++ b/src/domain/collaboration/post/post.resolver.mutations.ts @@ -30,7 +30,7 @@ export class PostResolverMutations { agentInfo, post.authorization, AuthorizationPrivilege.DELETE, - `delete post: ${post.nameID}` + `delete post: ${post.id}` ); return await this.postService.deletePost(deleteData.ID); } @@ -48,7 +48,7 @@ export class PostResolverMutations { agentInfo, post.authorization, AuthorizationPrivilege.UPDATE, - `update post: ${post.nameID}` + `update post: ${post.id}` ); return await this.postService.updatePost(postData); } diff --git a/src/domain/common/whiteboard/whiteboard.resolver.mutations.ts b/src/domain/common/whiteboard/whiteboard.resolver.mutations.ts index f850c63473..07bbc8fde1 100644 --- a/src/domain/common/whiteboard/whiteboard.resolver.mutations.ts +++ b/src/domain/common/whiteboard/whiteboard.resolver.mutations.ts @@ -34,7 +34,7 @@ export class WhiteboardResolverMutations { agentInfo, whiteboard.authorization, AuthorizationPrivilege.UPDATE, - `update Whiteboard: ${whiteboard.nameID}` + `update Whiteboard: ${whiteboard.id}` ); return this.whiteboardService.updateWhiteboard(whiteboard, whiteboardData); @@ -55,7 +55,7 @@ export class WhiteboardResolverMutations { agentInfo, whiteboard.authorization, AuthorizationPrivilege.UPDATE_CONTENT, - `update content of Whiteboard: ${whiteboard.nameID}` + `update content of Whiteboard: ${whiteboard.id}` ); return this.whiteboardService.updateWhiteboardContent( whiteboard, @@ -78,7 +78,7 @@ export class WhiteboardResolverMutations { agentInfo, whiteboard.authorization, AuthorizationPrivilege.DELETE, - `delete Whiteboard: ${whiteboard.nameID}` + `delete Whiteboard: ${whiteboard.id}` ); return await this.whiteboardService.deleteWhiteboard(whiteboard.id); diff --git a/src/domain/communication/messaging/mention.interface.ts b/src/domain/communication/messaging/mention.interface.ts index 4b3a38091f..ef6d0b9d9b 100644 --- a/src/domain/communication/messaging/mention.interface.ts +++ b/src/domain/communication/messaging/mention.interface.ts @@ -4,6 +4,6 @@ export enum MentionedEntityType { VIRTUAL_CONTRIBUTOR = 'vc', } export abstract class Mention { - nameId!: string; + id!: string; type!: MentionedEntityType; } diff --git a/src/domain/communication/room/room.module.ts b/src/domain/communication/room/room.module.ts index 1fdd41d67c..395283f566 100644 --- a/src/domain/communication/room/room.module.ts +++ b/src/domain/communication/room/room.module.ts @@ -21,6 +21,7 @@ import { VirtualContributorModule } from '@domain/community/virtual-contributor/ import { MessageModule } from '../message/message.module'; import { RoomServiceMentions } from './room.service.mentions'; import { VcInteractionModule } from '../vc-interaction/vc.interaction.module'; +import { ContributorLookupModule } from '@services/infrastructure/contributor-lookup/contributor.lookup.module'; @Module({ imports: [ @@ -36,6 +37,7 @@ import { VcInteractionModule } from '../vc-interaction/vc.interaction.module'; MessageModule, VcInteractionModule, VirtualContributorModule, + ContributorLookupModule, TypeOrmModule.forFeature([Room]), SubscriptionServiceModule, ], diff --git a/src/domain/communication/room/room.resolver.mutations.ts b/src/domain/communication/room/room.resolver.mutations.ts index daa29ec5ac..807cf0fe6f 100644 --- a/src/domain/communication/room/room.resolver.mutations.ts +++ b/src/domain/communication/room/room.resolver.mutations.ts @@ -72,7 +72,7 @@ export class RoomResolverMutations { const accessVirtualContributors = this.virtualContributorsEnabled(); - const mentions = this.roomServiceMentions.getMentionsFromText( + const mentions = await this.roomServiceMentions.getMentionsFromText( messageData.message ); @@ -272,9 +272,8 @@ export class RoomResolverMutations { ); const accessVirtualContributors = this.virtualContributorsEnabled(); - const mentions: Mention[] = this.roomServiceMentions.getMentionsFromText( - messageData.message - ); + const mentions: Mention[] = + await this.roomServiceMentions.getMentionsFromText(messageData.message); const threadID = messageData.threadID; const messageOwnerId = await this.roomService.getUserIdForMessage( diff --git a/src/domain/communication/room/room.service.mentions.ts b/src/domain/communication/room/room.service.mentions.ts index 4ac61de875..0a75f8e21b 100644 --- a/src/domain/communication/room/room.service.mentions.ts +++ b/src/domain/communication/room/room.service.mentions.ts @@ -15,10 +15,14 @@ import { RoomSendMessageReplyInput } from '@domain/communication/room/dto/room.d import { SubscriptionPublishService } from '@services/subscriptions/subscription-service/subscription.publish.service'; import { RoomService } from './room.service'; import { VirtualContributorService } from '@domain/community/virtual-contributor/virtual.contributor.service'; -import { EntityNotInitializedException } from '@common/exceptions'; +import { + EntityNotFoundException, + EntityNotInitializedException, +} from '@common/exceptions'; import { VirtualContributorQuestionInput } from '@domain/community/virtual-contributor/dto/virtual.contributor.dto.question.input'; import { MessageService } from '../message/message.service'; import { IVcInteraction } from '../vc-interaction/vc.interaction.interface'; +import { ContributorLookupService } from '@services/infrastructure/contributor-lookup/contributor.lookup.service'; @Injectable() export class RoomServiceMentions { @@ -34,6 +38,7 @@ export class RoomServiceMentions { private messageService: MessageService, private subscriptionPublishService: SubscriptionPublishService, private virtualContributorService: VirtualContributorService, + private contributorLookupService: ContributorLookupService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} @@ -72,19 +77,19 @@ export class RoomServiceMentions { for (const vcMention of vcMentions) { this.logger.verbose?.( - `got mention for VC: ${vcMention.nameId}`, + `got mention for VC: ${vcMention.id}`, LogContext.VIRTUAL_CONTRIBUTOR ); if (!vcInteraction) { vcInteraction = await this.roomService.addVcInteractionToRoom({ - virtualContributorID: vcMention.nameId, + virtualContributorID: vcMention.id, roomID: room.id, threadID: threadID, }); } await this.askQuestionToVirtualContributor( - vcMention.nameId, + vcMention.id, question, threadID, agentInfo, @@ -96,7 +101,7 @@ export class RoomServiceMentions { } public async askQuestionToVirtualContributor( - nameID: string, + uuid: string, question: string, threadID: string, agentInfo: AgentInfo, @@ -105,7 +110,7 @@ export class RoomServiceMentions { vcInteraction: IVcInteraction | undefined = undefined ) { const virtualContributor = - await this.virtualContributorService.getVirtualContributor(nameID, { + await this.virtualContributorService.getVirtualContributor(uuid, { relations: { aiPersona: true, }, @@ -115,7 +120,7 @@ export class RoomServiceMentions { if (!virtualPersona) { throw new EntityNotInitializedException( - `VirtualPersona not loaded for VirtualContributor ${virtualContributor?.nameID}`, + `VirtualPersona not loaded for VirtualContributor ${virtualContributor?.id}`, LogContext.VIRTUAL_CONTRIBUTOR ); } @@ -180,24 +185,43 @@ export class RoomServiceMentions { this.notificationAdapter.entityMentions(entityMentionsNotificationInput); } - public getMentionsFromText(text: string): Mention[] { + public async getMentionsFromText(text: string): Promise { const result: Mention[] = []; for (const match of text.matchAll(this.MENTION_REGEX_ALL)) { + const contributorNamedID = match.groups?.nameid; + if (!contributorNamedID) { + throw new EntityNotFoundException( + `No nameID found in mention: ${match}`, + LogContext.COMMUNICATION + ); + } if (match.groups?.type === MentionedEntityType.USER) { + const user = + await this.contributorLookupService.getUserByNameIdOrFail( + contributorNamedID + ); result.push({ - nameId: match.groups.nameid, + id: user.id, type: MentionedEntityType.USER, }); } else if (match.groups?.type === MentionedEntityType.ORGANIZATION) { + const organization = + await this.contributorLookupService.getOrganizationByNameIdOrFail( + contributorNamedID + ); result.push({ - nameId: match.groups.nameid, + id: organization.id, type: MentionedEntityType.ORGANIZATION, }); } else if ( match.groups?.type === MentionedEntityType.VIRTUAL_CONTRIBUTOR ) { + const virtualContributor = + await this.contributorLookupService.getVirtualContributorByNameIdOrFail( + contributorNamedID + ); result.push({ - nameId: match.groups.nameid, + id: virtualContributor.id, type: MentionedEntityType.VIRTUAL_CONTRIBUTOR, }); } diff --git a/src/domain/community/community-role/community.role.service.ts b/src/domain/community/community-role/community.role.service.ts index 90235c4eea..73b39184e3 100644 --- a/src/domain/community/community-role/community.role.service.ts +++ b/src/domain/community/community-role/community.role.service.ts @@ -962,7 +962,7 @@ export class CommunityRoleService { const isExistingMember = await this.isMember(agent, community); if (isExistingMember) throw new CommunityMembershipException( - `Contributor ${user.nameID} is already a member of the Community: ${community.id}.`, + `Contributor ${user.id} is already a member of the Community: ${community.id}.`, LogContext.COMMUNITY ); } @@ -998,7 +998,7 @@ export class CommunityRoleService { const isExistingMember = await this.isMember(agent, community); if (isExistingMember) throw new CommunityMembershipException( - `Contributor ${contributor.nameID} is already a member of the Community: ${community.id}.`, + `Contributor ${contributor.id} is already a member of the Community: ${community.id}.`, LogContext.COMMUNITY ); } diff --git a/src/domain/community/organization-role/organization.role.resolver.fields.ts b/src/domain/community/organization-role/organization.role.resolver.fields.ts index 813b6c0e32..da4b0c77a0 100644 --- a/src/domain/community/organization-role/organization.role.resolver.fields.ts +++ b/src/domain/community/organization-role/organization.role.resolver.fields.ts @@ -37,7 +37,7 @@ export class OrganizationRoleResolverFields { agentInfo, organization.authorization, AuthorizationPrivilege.READ, - `read associates on org: ${organization.nameID}` + `read associates on org: ${organization.id}` ); return await this.organizationRoleService.getAssociates(organization); @@ -60,7 +60,7 @@ export class OrganizationRoleResolverFields { agentInfo, organization.authorization, AuthorizationPrivilege.READ, - `read admins on org: ${organization.nameID}` + `read admins on org: ${organization.id}` ); return await this.organizationRoleService.getAdmins(organization); @@ -83,7 +83,7 @@ export class OrganizationRoleResolverFields { agentInfo, organization.authorization, AuthorizationPrivilege.READ, - `read owners on org: ${organization.nameID}` + `read owners on org: ${organization.id}` ); return await this.organizationRoleService.getOwners(organization); diff --git a/src/domain/community/organization-role/organization.role.resolver.mutations.ts b/src/domain/community/organization-role/organization.role.resolver.mutations.ts index 1446becd3b..631bd1fc35 100644 --- a/src/domain/community/organization-role/organization.role.resolver.mutations.ts +++ b/src/domain/community/organization-role/organization.role.resolver.mutations.ts @@ -41,7 +41,7 @@ export class OrganizationRoleResolverMutations { agentInfo, organization.authorization, AuthorizationPrivilege.GRANT, - `assign organization role to user: ${organization.nameID} - ${membershipData.role}` + `assign organization role to user: ${organization.id} - ${membershipData.role}` ); return await this.organizationRoleService.assignOrganizationRoleToUser( membershipData @@ -76,7 +76,7 @@ export class OrganizationRoleResolverMutations { agentInfo, authorization, AuthorizationPrivilege.GRANT, - `remove user organization role from user: ${organization.nameID} - ${membershipData.role}` + `remove user organization role from user: ${organization.id} - ${membershipData.role}` ); return await this.organizationRoleService.removeOrganizationRoleFromUser( membershipData diff --git a/src/domain/community/organization-role/organization.role.service.ts b/src/domain/community/organization-role/organization.role.service.ts index 62c6a9749c..96dae0c4d7 100644 --- a/src/domain/community/organization-role/organization.role.service.ts +++ b/src/domain/community/organization-role/organization.role.service.ts @@ -199,7 +199,7 @@ export class OrganizationRoleService { }); if (orgOwners.length === 1) throw new ForbiddenException( - `Not allowed to remove last owner for organisaiton: ${organization.nameID}`, + `Not allowed to remove last owner for organisaiton: ${organization.id}`, LogContext.AUTH ); } diff --git a/src/domain/community/organization/organization.resolver.fields.ts b/src/domain/community/organization/organization.resolver.fields.ts index 11368e89f4..d4dfa3e845 100644 --- a/src/domain/community/organization/organization.resolver.fields.ts +++ b/src/domain/community/organization/organization.resolver.fields.ts @@ -64,7 +64,7 @@ export class OrganizationResolverFields { agentInfo, organization.authorization, AuthorizationPrivilege.READ, - `read user groups on org: ${organization.nameID}` + `read user groups on org: ${organization.id}` ); return await this.organizationService.getUserGroups(organization); @@ -90,7 +90,7 @@ export class OrganizationResolverFields { agentInfo, organization.authorization, AuthorizationPrivilege.READ, - `read single usergroup on org: ${organization.nameID}` + `read single usergroup on org: ${organization.id}` ); const userGroup = await this.groupService.getUserGroupOrFail(groupID, { @@ -230,7 +230,7 @@ export class OrganizationResolverFields { agentInfo, organization.authorization, AuthorizationPrivilege.READ, - `read preferences on org: ${organization.nameID}` + `read preferences on org: ${organization.id}` ); const preferenceSet = await this.organizationService.getPreferenceSetOrFail( organization.id diff --git a/src/domain/community/organization/organization.resolver.mutations.ts b/src/domain/community/organization/organization.resolver.mutations.ts index faba6584a7..c3aa46c3e6 100644 --- a/src/domain/community/organization/organization.resolver.mutations.ts +++ b/src/domain/community/organization/organization.resolver.mutations.ts @@ -51,7 +51,7 @@ export class OrganizationResolverMutations { agentInfo, authorizationPolicy, AuthorizationPrivilege.CREATE_ORGANIZATION, - `create Organization: ${organizationData.nameID}` + `create Organization: ${organizationData.profileData.displayName}` ); const organization = await this.organizationService.createOrganization( organizationData, @@ -79,7 +79,7 @@ export class OrganizationResolverMutations { agentInfo, organization.authorization, AuthorizationPrivilege.CREATE, - `orgCreateGroup: ${organization.nameID}` + `orgCreateGroup: ${organization.id}` ); const group = await this.organizationService.createGroup(groupData); @@ -105,7 +105,7 @@ export class OrganizationResolverMutations { agentInfo, organization.authorization, AuthorizationPrivilege.UPDATE, - `orgUpdate: ${organization.nameID}` + `orgUpdate: ${organization.id}` ); return await this.organizationService.updateOrganization(organizationData); @@ -126,7 +126,7 @@ export class OrganizationResolverMutations { agentInfo, organization.authorization, AuthorizationPrivilege.DELETE, - `deleteOrg: ${organization.nameID}` + `deleteOrg: ${organization.id}` ); return await this.organizationService.deleteOrganization(deleteData); } diff --git a/src/domain/community/organization/organization.service.ts b/src/domain/community/organization/organization.service.ts index db5caee5f4..c61f824fc0 100644 --- a/src/domain/community/organization/organization.service.ts +++ b/src/domain/community/organization/organization.service.ts @@ -509,7 +509,7 @@ export class OrganizationService { const groups = organizationGroups.groups; if (!groups) throw new ValidationException( - `No groups on organization: ${organization.nameID}`, + `No groups on organization: ${organization.id}`, LogContext.COMMUNITY ); return groups; @@ -527,7 +527,7 @@ export class OrganizationService { if (!preferenceSet) { throw new EntityNotFoundException( - `Unable to find preferenceSet for organization with nameID: ${orgWithPreferences.nameID}`, + `Unable to find preferenceSet for organization with nameID: ${orgWithPreferences.id}`, LogContext.COMMUNITY ); } @@ -551,7 +551,7 @@ export class OrganizationService { if (!storageAggregator) { throw new EntityNotFoundException( - `Unable to find storageAggregator for Organization with nameID: ${organizationWithStorageAggregator.nameID}`, + `Unable to find storageAggregator for Organization with nameID: ${organizationWithStorageAggregator.id}`, LogContext.COMMUNITY ); } @@ -616,7 +616,7 @@ export class OrganizationService { ); if (!organization.verification) { throw new EntityNotFoundException( - `Unable to load verification for organisation: ${organization.nameID}`, + `Unable to load verification for organisation: ${organization.id}`, LogContext.COMMUNITY ); } diff --git a/src/domain/community/user/user.service.ts b/src/domain/community/user/user.service.ts index bc352f69e1..b507e9251b 100644 --- a/src/domain/community/user/user.service.ts +++ b/src/domain/community/user/user.service.ts @@ -162,7 +162,7 @@ export class UserService { }); this.logger.verbose?.( - `Created a new user with nameID: ${user.nameID}`, + `Created a new user with email: ${user.email}`, LogContext.COMMUNITY ); @@ -467,7 +467,7 @@ export class UserService { if (!user.preferenceSet) { throw new EntityNotInitializedException( - `User preferences not initialized or not found for user with nameID: ${user.nameID}`, + `User preferences not initialized or not found for user with nameID: ${user.id}`, LogContext.COMMUNITY ); } @@ -860,7 +860,7 @@ export class UserService { const profile = userWithProfile.profile; if (!profile) throw new RelationshipNotFoundException( - `Unable to load Profile for User: ${user.nameID} `, + `Unable to load Profile for User: ${user.id} `, LogContext.COMMUNITY ); diff --git a/src/domain/community/virtual-contributor/virtual.contributor.resolver.fields.ts b/src/domain/community/virtual-contributor/virtual.contributor.resolver.fields.ts index 1e936985c0..a6dbf78d4a 100644 --- a/src/domain/community/virtual-contributor/virtual.contributor.resolver.fields.ts +++ b/src/domain/community/virtual-contributor/virtual.contributor.resolver.fields.ts @@ -68,7 +68,7 @@ export class VirtualContributorResolverFields { agentInfo, virtual.authorization, AuthorizationPrivilege.READ, - `virtual authorization access: ${virtual.nameID}` + `virtual authorization access: ${virtual.id}` ); return virtual.authorization; diff --git a/src/domain/community/virtual-contributor/virtual.contributor.resolver.mutations.ts b/src/domain/community/virtual-contributor/virtual.contributor.resolver.mutations.ts index 5a137c9140..5d1c83bdf7 100644 --- a/src/domain/community/virtual-contributor/virtual.contributor.resolver.mutations.ts +++ b/src/domain/community/virtual-contributor/virtual.contributor.resolver.mutations.ts @@ -39,7 +39,7 @@ export class VirtualContributorResolverMutations { agentInfo, virtual.authorization, AuthorizationPrivilege.UPDATE, - `orgUpdate: ${virtual.nameID}` + `virtual contribtor Update: ${virtual.id}` ); return await this.virtualContributorService.updateVirtualContributor( @@ -63,7 +63,7 @@ export class VirtualContributorResolverMutations { agentInfo, virtual.authorization, AuthorizationPrivilege.DELETE, - `deleteOrg: ${virtual.nameID}` + `delete virtual contributor: ${virtual.id}` ); return await this.virtualContributorService.deleteVirtualContributor( deleteData.ID @@ -93,7 +93,7 @@ export class VirtualContributorResolverMutations { agentInfo, virtual.authorization, AuthorizationPrivilege.UPDATE, - `deleteOrg: ${virtual.nameID}` + `refresh body of knowledge: ${virtual.id}` ); return await this.virtualContributorService.refershBodyOfKnowledge( virtual, diff --git a/src/domain/community/virtual-contributor/virtual.contributor.service.ts b/src/domain/community/virtual-contributor/virtual.contributor.service.ts index 530c443ccc..9ead4c849e 100644 --- a/src/domain/community/virtual-contributor/virtual.contributor.service.ts +++ b/src/domain/community/virtual-contributor/virtual.contributor.service.ts @@ -197,10 +197,6 @@ export class VirtualContributorService { } if (virtualContributorData.nameID) { - this.logger.verbose?.( - `${virtualContributorData.nameID} - ${virtual.nameID}`, - LogContext.COMMUNICATION - ); if ( virtualContributorData.nameID.toLowerCase() !== virtual.nameID.toLowerCase() @@ -485,7 +481,7 @@ export class VirtualContributorService { if (!aiPersona) { throw new EntityNotFoundException( - `Unable to find aiPersona for VirtualContributor: ${virtualContributor.nameID}`, + `Unable to find aiPersona for VirtualContributor: ${virtualContributor.id}`, LogContext.VIRTUAL_CONTRIBUTOR ); } diff --git a/src/domain/space/account/account.resolver.mutations.ts b/src/domain/space/account/account.resolver.mutations.ts index 69057b971b..f4ca5778fe 100644 --- a/src/domain/space/account/account.resolver.mutations.ts +++ b/src/domain/space/account/account.resolver.mutations.ts @@ -78,7 +78,7 @@ export class AccountResolverMutations { agentInfo, authorizationPolicy, AuthorizationPrivilege.CREATE_SPACE, - `create space: ${accountData.spaceData?.nameID}` + `create account with space: ${accountData}` ); let account = await this.accountService.createAccount(accountData); @@ -162,7 +162,7 @@ export class AccountResolverMutations { agentInfo, account.authorization, AuthorizationPrivilege.DELETE, - `deleteSpace + account: ${space.nameID}` + `deleteSpace + account: ${space.id}` ); await this.accountService.deleteAccount(account); return space; @@ -172,7 +172,7 @@ export class AccountResolverMutations { agentInfo, space.authorization, AuthorizationPrivilege.DELETE, - `deleteSpace: ${space.nameID}` + `deleteSpace: ${space.id}` ); return await this.spaceService.deleteSpace(deleteData); default: @@ -352,7 +352,7 @@ export class AccountResolverMutations { agentInfo, account.authorization, AuthorizationPrivilege.CREATE_VIRTUAL_CONTRIBUTOR, - `create Virtual contributor: ${virtualContributorData.nameID}` + `create Virtual contributor on account: ${account.id}` ); let virtual = await this.accountService.createVirtualContributorOnAccount( @@ -417,7 +417,7 @@ export class AccountResolverMutations { agentInfo, account.authorization, AuthorizationPrivilege.CREATE, - `create Innovation Pack on account: ${innovationPackData.nameID}` + `create Innovation Pack on account: ${account.id}` ); let innovationPack = diff --git a/src/domain/space/space/space.resolver.mutations.ts b/src/domain/space/space/space.resolver.mutations.ts index f7fb9b599b..cb2006cd90 100644 --- a/src/domain/space/space/space.resolver.mutations.ts +++ b/src/domain/space/space/space.resolver.mutations.ts @@ -53,7 +53,7 @@ export class SpaceResolverMutations { agentInfo, space.authorization, AuthorizationPrivilege.UPDATE, - `updateSpace: ${space.nameID}` + `update Space: ${space.id}` ); // ensure working with UUID @@ -190,7 +190,7 @@ export class SpaceResolverMutations { agentInfo, space.authorization, AuthorizationPrivilege.CREATE_SUBSPACE, - `challengeCreate: ${space.nameID}` + `subspace create in: ${space.id}` ); // For the creation based on the template from another challenge require platform admin privileges @@ -199,7 +199,7 @@ export class SpaceResolverMutations { agentInfo, space.authorization, AuthorizationPrivilege.CREATE, - `challengeCreate using challenge template: ${space.nameID} - ${subspaceData.collaborationData.collaborationTemplateID}` + `subspaceCreate using space template: ${space.id} - ${subspaceData.collaborationData.collaborationTemplateID}` ); } let subspace = await this.spaceService.createSubspace( diff --git a/src/domain/space/space/space.service.ts b/src/domain/space/space/space.service.ts index 4c6a9229c0..c3f7a9ed8e 100644 --- a/src/domain/space/space/space.service.ts +++ b/src/domain/space/space/space.service.ts @@ -269,7 +269,7 @@ export class SpaceService { // Do not remove a space that has subspaces, require these to be individually first removed if (space.subspaces.length > 0) throw new OperationNotAllowedException( - `Unable to remove Space (${space.nameID}) as it contains ${space.subspaces.length} subspaces`, + `Unable to remove Space (${space.id}) as it contains ${space.subspaces.length} subspaces`, LogContext.SPACES ); diff --git a/src/domain/storage/storage-aggregator/storage.aggregator.service.ts b/src/domain/storage/storage-aggregator/storage.aggregator.service.ts index 04b1b0ce18..4ee232d71e 100644 --- a/src/domain/storage/storage-aggregator/storage.aggregator.service.ts +++ b/src/domain/storage/storage-aggregator/storage.aggregator.service.ts @@ -101,15 +101,12 @@ export class StorageAggregatorService { public async size(storageAggregator: IStorageAggregator): Promise { const directStorage = await this.getDirectStorageBucket(storageAggregator); - const directStorageSize = await this.storageBucketService.size( - directStorage - ); - const childStorageAggregatorsSize = await this.sizeChildStorageAggregators( - storageAggregator - ); - const childStorageBucketsSize = await this.sizeChildStorageBuckets( - storageAggregator - ); + const directStorageSize = + await this.storageBucketService.size(directStorage); + const childStorageAggregatorsSize = + await this.sizeChildStorageAggregators(storageAggregator); + const childStorageBucketsSize = + await this.sizeChildStorageBuckets(storageAggregator); const totalSize = +directStorageSize + +childStorageBucketsSize + @@ -135,9 +132,8 @@ export class StorageAggregatorService { public async sizeChildStorageAggregators( storageAggregator: IStorageAggregator ): Promise { - const childStorageAggregators = await this.getChildStorageAggregators( - storageAggregator - ); + const childStorageAggregators = + await this.getChildStorageAggregators(storageAggregator); let result = 0; for (const childStorageAggregator of childStorageAggregators) { const size = await this.size(childStorageAggregator); diff --git a/src/domain/timeline/event/event.resolver.mutations.ts b/src/domain/timeline/event/event.resolver.mutations.ts index 8e4905cc18..c057fc781f 100644 --- a/src/domain/timeline/event/event.resolver.mutations.ts +++ b/src/domain/timeline/event/event.resolver.mutations.ts @@ -31,7 +31,7 @@ export class CalendarEventResolverMutations { agentInfo, calendarEvent.authorization, AuthorizationPrivilege.DELETE, - `delete calendarEvent: ${calendarEvent.nameID}` + `delete calendarEvent: ${calendarEvent.id}` ); return await this.calendarEventService.deleteCalendarEvent(deleteData); } @@ -50,7 +50,7 @@ export class CalendarEventResolverMutations { agentInfo, calendarEvent.authorization, AuthorizationPrivilege.UPDATE, - `update calendarEvent: ${calendarEvent.nameID}` + `update calendarEvent: ${calendarEvent.id}` ); return await this.calendarEventService.updateCalendarEvent(eventData); } diff --git a/src/library/innovation-pack/innovation.pack.resolver.mutations.ts b/src/library/innovation-pack/innovation.pack.resolver.mutations.ts index 93033d8f22..b519f91185 100644 --- a/src/library/innovation-pack/innovation.pack.resolver.mutations.ts +++ b/src/library/innovation-pack/innovation.pack.resolver.mutations.ts @@ -35,7 +35,7 @@ export class InnovationPackResolverMutations { agentInfo, innovationPack.authorization, AuthorizationPrivilege.UPDATE, - `updateInnovationPack: ${innovationPack.nameID}` + `updateInnovationPack: ${innovationPack.id}` ); // ensure working with UUID @@ -58,7 +58,7 @@ export class InnovationPackResolverMutations { agentInfo, innovationPack.authorization, AuthorizationPrivilege.DELETE, - `deleteInnovationPack: ${innovationPack.nameID}` + `deleteInnovationPack: ${innovationPack.id}` ); return await this.innovationPackService.deleteInnovationPack(deleteData); } diff --git a/src/library/innovation-pack/innovaton.pack.service.ts b/src/library/innovation-pack/innovaton.pack.service.ts index 8b9dbee401..b4d50756ef 100644 --- a/src/library/innovation-pack/innovaton.pack.service.ts +++ b/src/library/innovation-pack/innovaton.pack.service.ts @@ -198,7 +198,7 @@ export class InnovationPackService { if (!templatesSet) { throw new EntityNotFoundException( - `Unable to find templatesSet for innovationPack with nameID: ${innovationPackWithTemplates.nameID}`, + `Unable to find templatesSet for innovationPack with nameID: ${innovationPackWithTemplates.id}`, LogContext.COMMUNITY ); } diff --git a/src/platform/settings/platform.settings.resolver.mutations.ts b/src/platform/settings/platform.settings.resolver.mutations.ts index 8c28520ccc..93ace3fd8d 100644 --- a/src/platform/settings/platform.settings.resolver.mutations.ts +++ b/src/platform/settings/platform.settings.resolver.mutations.ts @@ -77,7 +77,7 @@ export class PlatformSettingsResolverMutations { agentInfo, organization.authorization, AuthorizationPrivilege.PLATFORM_ADMIN, - `organization update platform settings: ${organization.nameID}` + `organization update platform settings: ${organization.id}` ); return await this.platformSettingsService.updateOrganizationPlatformSettings( diff --git a/src/services/adapters/activity-adapter/activity.adapter.ts b/src/services/adapters/activity-adapter/activity.adapter.ts index d993ad1490..c322808a09 100644 --- a/src/services/adapters/activity-adapter/activity.adapter.ts +++ b/src/services/adapters/activity-adapter/activity.adapter.ts @@ -342,7 +342,7 @@ export class ActivityAdapter { const collaborationID = await this.getCollaborationIdFromCommunity( community.id ); - const description = `${eventData.contributor.nameID}`; + const description = `${eventData.contributor.id}`; const activity = await this.activityService.createActivity({ triggeredBy: eventData.triggeredBy, collaborationID, @@ -404,9 +404,8 @@ export class ActivityAdapter { const updates = eventData.updates; const communityID = await this.getCommunityIdFromUpdates(updates.id); - const collaborationID = await this.getCollaborationIdFromCommunity( - communityID - ); + const collaborationID = + await this.getCollaborationIdFromCommunity(communityID); const activity = await this.activityService.createActivity({ triggeredBy: eventData.triggeredBy, diff --git a/src/services/adapters/notification-adapter/notification.adapter.ts b/src/services/adapters/notification-adapter/notification.adapter.ts index eecbd0a3b6..e124ecce0d 100644 --- a/src/services/adapters/notification-adapter/notification.adapter.ts +++ b/src/services/adapters/notification-adapter/notification.adapter.ts @@ -274,7 +274,7 @@ export class NotificationAdapter { const entityMentionNotificationInput: NotificationInputEntityMention = { triggeredBy: eventData.triggeredBy, comment: eventData.comment, - mentionedEntityID: mention.nameId, + mentionedEntityID: mention.id, commentsId: eventData.roomId, originEntity: eventData.originEntity, commentType: eventData.commentType, diff --git a/src/services/adapters/notification-adapter/notification.payload.builder.ts b/src/services/adapters/notification-adapter/notification.payload.builder.ts index 57dbbf9ddc..7e17a54e57 100644 --- a/src/services/adapters/notification-adapter/notification.payload.builder.ts +++ b/src/services/adapters/notification-adapter/notification.payload.builder.ts @@ -566,7 +566,7 @@ export class NotificationPayloadBuilder { this.contributorLookupService.getContributorType(contributor); const userURL = - await this.urlGeneratorService.createUrlForContributor(contributor); + this.urlGeneratorService.createUrlForContributor(contributor); const result: ContributorPayload = { id: contributor.id, nameID: contributor.nameID, @@ -613,17 +613,14 @@ export class NotificationPayloadBuilder { async buildCommunicationUserMentionNotificationPayload( senderID: string, - mentionedUserNameID: string, + mentionedUserUUID: string, comment: string, originEntityId: string, originEntityDisplayName: string, commentType: RoomType ): Promise { - const user = - await this.contributorLookupService.getUserByNameIdOrFail( - mentionedUserNameID - ); - const userContributor = await this.getContributorPayloadOrFail(user.id); + const userContributor = + await this.getContributorPayloadOrFail(mentionedUserUUID); const commentOriginUrl = await this.buildCommentOriginUrl( commentType, @@ -647,17 +644,13 @@ export class NotificationPayloadBuilder { async buildCommunicationOrganizationMentionNotificationPayload( senderID: string, - mentionedOrgNameID: string, + mentionedOrgUUID: string, comment: string, originEntityId: string, originEntityDisplayName: string, commentType: RoomType ): Promise { - const org = - await this.contributorLookupService.getOrganizationByNameIdOrFail( - mentionedOrgNameID - ); - const orgData = await this.getContributorPayloadOrFail(org.id); + const orgData = await this.getContributorPayloadOrFail(mentionedOrgUUID); const commentOriginUrl = await this.buildCommentOriginUrl( commentType, diff --git a/src/services/api/conversion/conversion.resolver.mutations.ts b/src/services/api/conversion/conversion.resolver.mutations.ts index e91d8264da..f1a81ce27f 100644 --- a/src/services/api/conversion/conversion.resolver.mutations.ts +++ b/src/services/api/conversion/conversion.resolver.mutations.ts @@ -89,7 +89,7 @@ export class ConversionResolverMutations { ); if (!subsubspace.account || !subsubspace.account.space) { throw new EntityNotInitializedException( - `account not found on opportunity: ${subsubspace.nameID}`, + `account not found on subsubspace: ${subsubspace.id}`, LogContext.SPACES ); } diff --git a/src/services/api/conversion/conversion.service.ts b/src/services/api/conversion/conversion.service.ts index 103bef2f97..e57cbd24ab 100644 --- a/src/services/api/conversion/conversion.service.ts +++ b/src/services/api/conversion/conversion.service.ts @@ -74,7 +74,7 @@ export class ConversionService { !subspace.storageAggregator ) { throw new EntityNotInitializedException( - `Unable to locate all entities on on subspace: ${subspace.nameID}`, + `Unable to locate all entities on on subspace: ${subspace.id}`, LogContext.CONVERSION ); } @@ -86,13 +86,13 @@ export class ConversionService { ); if (challengeCommunityLeadOrgs.length !== 1) { throw new ValidationException( - `A Subspace must have exactly one Lead organization to be converted to a Space: ${subspace.nameID} has ${challengeCommunityLeadOrgs.length}`, + `A Subspace must have exactly one Lead organization to be converted to a Space: ${subspace.id} has ${challengeCommunityLeadOrgs.length}`, LogContext.CONVERSION ); } const hostOrg = challengeCommunityLeadOrgs[0]; const createAccountInput: CreateAccountInput = { - hostID: hostOrg.nameID, + hostID: hostOrg.id, spaceData: { nameID: subspace.nameID, profileData: { @@ -131,7 +131,7 @@ export class ConversionService { !space.storageAggregator ) { throw new EntityNotInitializedException( - `Unable to locate all entities on new Space: ${space.nameID}`, + `Unable to locate all entities on new Space: ${space.id}`, LogContext.CONVERSION ); } @@ -260,7 +260,7 @@ export class ConversionService { !subsubspace.collaboration.callouts ) { throw new EntityNotInitializedException( - `Unable to locate all entities on on Opportunity: ${subsubspace.nameID}`, + `Unable to locate all entities on on Opportunity: ${subsubspace.id}`, LogContext.CONVERSION ); } @@ -320,7 +320,7 @@ export class ConversionService { !subspace.storageAggregator ) { throw new EntityNotInitializedException( - `Unable to locate all entities on new Challenge for converting opportunity: ${subspace.nameID}`, + `Unable to locate all entities on new Subspace for converting subsubspace: ${subspace.id}`, LogContext.CONVERSION ); } @@ -443,7 +443,7 @@ export class ConversionService { !callout.framing.profile.tagsets ) { throw new EntityNotInitializedException( - `Unable to locate all child entities on callout: ${callout.nameID}`, + `Unable to locate all child entities on callout: ${callout.id}`, LogContext.CONVERSION ); } @@ -483,7 +483,7 @@ export class ConversionService { !callout.framing.profile.tagsets ) { throw new EntityNotInitializedException( - `Unable to locate all child entities on challenge callout: ${callout.nameID}`, + `Unable to locate all child entities on challenge callout: ${callout.id}`, LogContext.CONVERSION ); } diff --git a/src/services/api/lookup/lookup.resolver.fields.ts b/src/services/api/lookup/lookup.resolver.fields.ts index da323c7514..b006b05ba0 100644 --- a/src/services/api/lookup/lookup.resolver.fields.ts +++ b/src/services/api/lookup/lookup.resolver.fields.ts @@ -435,7 +435,7 @@ export class LookupResolverFields { agentInfo, whiteboard.authorization, AuthorizationPrivilege.READ, - `lookup Whiteboard: ${whiteboard.nameID}` + `lookup Whiteboard: ${whiteboard.id}` ); return whiteboard; diff --git a/src/services/api/registration/registration.service.ts b/src/services/api/registration/registration.service.ts index 0f1a99bc91..b8db5522dc 100644 --- a/src/services/api/registration/registration.service.ts +++ b/src/services/api/registration/registration.service.ts @@ -81,7 +81,7 @@ export class RegistrationService { ).value === 'true'; if (!orgMatchDomain) { this.logger.verbose?.( - `Organization '${org.nameID}' preference ${OrganizationPreferenceType.AUTHORIZATION_ORGANIZATION_MATCH_DOMAIN} is disabled`, + `Organization '${org.id}' preference ${OrganizationPreferenceType.AUTHORIZATION_ORGANIZATION_MATCH_DOMAIN} is disabled`, LogContext.COMMUNITY ); return false; @@ -93,7 +93,7 @@ export class RegistrationService { OrganizationVerificationEnum.VERIFIED_MANUAL_ATTESTATION ) { this.logger.verbose?.( - `Organization '${org.nameID}' not verified`, + `Organization '${org.id}' not verified`, LogContext.COMMUNITY ); return false; @@ -106,7 +106,7 @@ export class RegistrationService { }); this.logger.verbose?.( - `User ${user.nameID} successfully added to Organization '${org.nameID}'`, + `User ${user.id} successfully added to Organization '${org.id}'`, LogContext.COMMUNITY ); return true; diff --git a/src/services/api/roles/util/get.space.roles.for.contributor.query.result.ts b/src/services/api/roles/util/get.space.roles.for.contributor.query.result.ts index 59059fc690..df4cc11e5f 100644 --- a/src/services/api/roles/util/get.space.roles.for.contributor.query.result.ts +++ b/src/services/api/roles/util/get.space.roles.for.contributor.query.result.ts @@ -23,7 +23,7 @@ export const getSpaceRolesForContributorQueryResult = ( // Only return children of spaces that the current user has READ access to if (!space.authorization) { throw new RelationshipNotFoundException( - `Unable to load authorization on Space in roles user: ${space.nameID}`, + `Unable to load authorization on Space in roles user: ${space.id}`, LogContext.ROLES ); } @@ -37,7 +37,7 @@ export const getSpaceRolesForContributorQueryResult = ( const levelZeroSpaceID = space.levelZeroSpaceID; if (!levelZeroSpaceID) { throw new RelationshipNotFoundException( - `Unable to load account on Space in roles user: ${space.nameID}`, + `Unable to load account on Space in roles user: ${space.id}`, LogContext.ROLES ); } @@ -46,7 +46,7 @@ export const getSpaceRolesForContributorQueryResult = ( const challengeLevelZeroSpaceID = subspace.levelZeroSpaceID; if (!challengeLevelZeroSpaceID) { throw new RelationshipNotFoundException( - `Unable to load L0 space ID on Challenge in roles user: ${space.nameID}`, + `Unable to load L0 space ID on Subspace in roles user: ${space.id}`, LogContext.ROLES ); } diff --git a/src/services/api/search/v1/search.result.builder.service.ts b/src/services/api/search/v1/search.result.builder.service.ts index 60fd0b9776..20daa0cf56 100644 --- a/src/services/api/search/v1/search.result.builder.service.ts +++ b/src/services/api/search/v1/search.result.builder.service.ts @@ -71,7 +71,7 @@ export default class SearchResultBuilderService ); if (!subspace.account || !subspace.account.space) { throw new RelationshipNotFoundException( - `Unable to find account for ${subspace.nameID}`, + `Unable to find account for ${subspace.id}`, LogContext.SEARCH ); } @@ -98,14 +98,14 @@ export default class SearchResultBuilderService ); if (!subsubspace.account || !subsubspace.account.space) { throw new RelationshipNotFoundException( - `Unable to find account for ${subsubspace.nameID}`, + `Unable to find account for ${subsubspace.id}`, LogContext.SEARCH ); } const space = subsubspace.account.space; if (!subsubspace.parentSpace) { throw new RelationshipNotFoundException( - `Unable to find parent subspace for ${subsubspace.nameID}`, + `Unable to find parent subspace for ${subsubspace.id}`, LogContext.SEARCH ); } diff --git a/src/services/infrastructure/contributor-lookup/contributor.lookup.service.ts b/src/services/infrastructure/contributor-lookup/contributor.lookup.service.ts index 97535b7fd7..3c9bac9b96 100644 --- a/src/services/infrastructure/contributor-lookup/contributor.lookup.service.ts +++ b/src/services/infrastructure/contributor-lookup/contributor.lookup.service.ts @@ -12,7 +12,10 @@ import { } from '@common/exceptions'; import { AuthorizationCredential, LogContext } from '@common/enums'; import { Credential, CredentialsSearchInput, ICredential } from '@domain/agent'; -import { VirtualContributor } from '@domain/community/virtual-contributor'; +import { + IVirtualContributor, + VirtualContributor, +} from '@domain/community/virtual-contributor'; import { IOrganization, Organization } from '@domain/community/organization'; import { CommunityContributorType } from '@common/enums/community.contributor.type'; import { InvalidUUID } from '@common/exceptions/invalid.uuid'; @@ -105,6 +108,23 @@ export class ContributorLookupService { return organization; } + async getVirtualContributorByNameIdOrFail( + virtualContributorNameID: string, + options?: FindOneOptions + ): Promise { + const virtualContributor: IVirtualContributor | null = + await this.entityManager.findOne(VirtualContributor, { + ...options, + where: { ...options?.where, nameID: virtualContributorNameID }, + }); + if (!virtualContributor) + throw new EntityNotFoundException( + `Unable to find VirtualContributor with NameID: ${virtualContributorNameID}`, + LogContext.COMMUNITY + ); + return virtualContributor; + } + async getOrganizationOrFail( organizationID: string, options?: FindOneOptions From 9471968de90c169a4d39bb4a75173a98d65a4ce8 Mon Sep 17 00:00:00 2001 From: Neil Smyth Date: Mon, 5 Aug 2024 17:07:35 +0100 Subject: [PATCH 14/27] add async to test for room mentions --- .../room/room.service.mentions.from.text.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/domain/communication/room/room.service.mentions.from.text.spec.ts b/src/domain/communication/room/room.service.mentions.from.text.spec.ts index 669e8c1981..c300f32c7e 100644 --- a/src/domain/communication/room/room.service.mentions.from.text.spec.ts +++ b/src/domain/communication/room/room.service.mentions.from.text.spec.ts @@ -92,8 +92,8 @@ describe('RoomServiceMentions', () => { { nameId: 'alex-org', type: 'organization' }, ], ], - ])('%s -> %j', (text, expected) => { - const result = service.getMentionsFromText(text); + ])('%s -> %j', async (text, expected) => { + const result = await service.getMentionsFromText(text); expect(result.length).toBe(expected.length); expect(result).toStrictEqual(expected); }); From a3f50d52287df8a45d326560ca0de9419cc99cc9 Mon Sep 17 00:00:00 2001 From: Neil Smyth Date: Mon, 5 Aug 2024 17:17:51 +0100 Subject: [PATCH 15/27] fixed mentions to have ids --- .../room.service.mentions.from.text.spec.ts | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/domain/communication/room/room.service.mentions.from.text.spec.ts b/src/domain/communication/room/room.service.mentions.from.text.spec.ts index c300f32c7e..2dc1f42a3f 100644 --- a/src/domain/communication/room/room.service.mentions.from.text.spec.ts +++ b/src/domain/communication/room/room.service.mentions.from.text.spec.ts @@ -22,74 +22,74 @@ describe('RoomServiceMentions', () => { ['no mentions here', []], [ 'Hey, [@aleksandar-alex](https://localhost/user/alex123) - this look like you', - [{ nameId: 'alex123', type: 'user' }], + [{ id: 'alex123', type: 'user' }], ], [ 'Hey, [@aleksandar-alex](http://localhost:3000/user/alex) - this look like you', - [{ nameId: 'alex', type: 'user' }], + [{ id: 'alex', type: 'user' }], ], [ 'Hey, [@aleksandar-alex](https://localhost:3000/user/alex) - this look like you', - [{ nameId: 'alex', type: 'user' }], + [{ id: 'alex', type: 'user' }], ], [ 'Hey, [@aleksandar](http://localhost:3000/user/alex-alex) - this look like you', - [{ nameId: 'alex-alex', type: 'user' }], + [{ id: 'alex-alex', type: 'user' }], ], [ 'Hey, [@aleksandar](https://localhost:3000/user/alex-alex) - this look like you', - [{ nameId: 'alex-alex', type: 'user' }], + [{ id: 'alex-alex', type: 'user' }], ], [ 'Hey, [@aleksandar-alex](http://localhost:3000/organization/alex) - this look like you', - [{ nameId: 'alex', type: 'organization' }], + [{ id: 'alex', type: 'organization' }], ], [ 'Hey, [@aleksandar-alex](https://localhost:3000/organization/alex) - this look like you', - [{ nameId: 'alex', type: 'organization' }], + [{ id: 'alex', type: 'organization' }], ], [ 'Hey, [@aleksandar](http://localhost:3000/organization/alex-alex) - this look like you', - [{ nameId: 'alex-alex', type: 'organization' }], + [{ id: 'alex-alex', type: 'organization' }], ], [ 'Hey, [@aleksandar](https://localhost:3000/organization/alex-alex) - this look like you', - [{ nameId: 'alex-alex', type: 'organization' }], + [{ id: 'alex-alex', type: 'organization' }], ], [ 'Hey, [@aleksandar](http://localhost:3000/user/alex) - this look like you', - [{ nameId: 'alex', type: 'user' }], + [{ id: 'alex', type: 'user' }], ], [ 'Hey, [@aleksandar](https://localhost:3000/user/alex) - this look like you', - [{ nameId: 'alex', type: 'user' }], + [{ id: 'alex', type: 'user' }], ], [ 'Hey, [@aleksandar](http://localhost:3000/organization/alex) - this look like you', - [{ nameId: 'alex', type: 'organization' }], + [{ id: 'alex', type: 'organization' }], ], [ 'Hey, [@aleksandar](https://localhost:3000/organization/alex) - this look like you', - [{ nameId: 'alex', type: 'organization' }], + [{ id: 'alex', type: 'organization' }], ], [ 'Hey, [@aleksandar](http://localhost:3000/user/alex) - this look like you\n' + 'Hey, [@aleksandar](http://localhost:3000/organization/alex-org) - this look like you', [ - { nameId: 'alex', type: 'user' }, - { nameId: 'alex-org', type: 'organization' }, + { id: 'alex', type: 'user' }, + { id: 'alex-org', type: 'organization' }, ], ], [ 'Hey, [@aleksandar](https://localhost:3000/user/alex) - this look like you\n' + 'Hey, [@aleksandar](https://localhost:3000/organization/alex-org) - this look like you', [ - { nameId: 'alex', type: 'user' }, - { nameId: 'alex-org', type: 'organization' }, + { id: 'alex', type: 'user' }, + { id: 'alex-org', type: 'organization' }, ], ], ])('%s -> %j', async (text, expected) => { From f98d9827616046d656ad0689b8a523fc41c2c0f0 Mon Sep 17 00:00:00 2001 From: Valentin Yanakiev Date: Tue, 6 Aug 2024 11:29:31 +0300 Subject: [PATCH 16/27] Mention tests updated --- .../room.service.mentions.from.text.spec.ts | 69 +++++++++++++------ test/data/virtual-contributor.json | 6 ++ test/mocks/contributor.lookup.service.mock.ts | 13 ++++ test/utils/test-data.ts | 2 + 4 files changed, 69 insertions(+), 21 deletions(-) create mode 100644 test/data/virtual-contributor.json create mode 100644 test/mocks/contributor.lookup.service.mock.ts diff --git a/src/domain/communication/room/room.service.mentions.from.text.spec.ts b/src/domain/communication/room/room.service.mentions.from.text.spec.ts index 2dc1f42a3f..5c929994cf 100644 --- a/src/domain/communication/room/room.service.mentions.from.text.spec.ts +++ b/src/domain/communication/room/room.service.mentions.from.text.spec.ts @@ -2,19 +2,30 @@ import { Test, TestingModule } from '@nestjs/testing'; import { RoomServiceMentions } from './room.service.mentions'; import { defaultMockerFactory } from '@test/utils/default.mocker.factory'; import { MockWinstonProvider } from '@test/mocks'; +import { MockContributorLookupService } from '@test/mocks/contributor.lookup.service.mock'; +import { ContributorLookupService } from '@services/infrastructure/contributor-lookup/contributor.lookup.service'; +import { testData } from '@test/utils/test-data'; +import { IUser } from '@domain/community/user/user.interface'; +import { IVirtualContributor } from '@domain/community/virtual-contributor'; describe('RoomServiceMentions', () => { - let service: RoomServiceMentions; + let roomMentionsService: RoomServiceMentions; + let contributorLookupService: ContributorLookupService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [MockWinstonProvider, RoomServiceMentions], + providers: [ + MockWinstonProvider, + RoomServiceMentions, + MockContributorLookupService, + ], exports: [RoomServiceMentions], }) .useMocker(defaultMockerFactory) .compile(); - service = module.get(RoomServiceMentions); + roomMentionsService = module.get(RoomServiceMentions); + contributorLookupService = module.get(ContributorLookupService); }); it.each([ @@ -22,78 +33,94 @@ describe('RoomServiceMentions', () => { ['no mentions here', []], [ 'Hey, [@aleksandar-alex](https://localhost/user/alex123) - this look like you', - [{ id: 'alex123', type: 'user' }], + [{ id: 'b69f82a1-bc7d-486c-85f9-e7ac6e689f4e', type: 'user' }], ], [ 'Hey, [@aleksandar-alex](http://localhost:3000/user/alex) - this look like you', - [{ id: 'alex', type: 'user' }], + [{ id: 'b69f82a1-bc7d-486c-85f9-e7ac6e689f4e', type: 'user' }], ], [ 'Hey, [@aleksandar-alex](https://localhost:3000/user/alex) - this look like you', - [{ id: 'alex', type: 'user' }], + [{ id: 'b69f82a1-bc7d-486c-85f9-e7ac6e689f4e', type: 'user' }], ], [ 'Hey, [@aleksandar](http://localhost:3000/user/alex-alex) - this look like you', - [{ id: 'alex-alex', type: 'user' }], + [{ id: 'b69f82a1-bc7d-486c-85f9-e7ac6e689f4e', type: 'user' }], ], [ 'Hey, [@aleksandar](https://localhost:3000/user/alex-alex) - this look like you', - [{ id: 'alex-alex', type: 'user' }], + [{ id: 'b69f82a1-bc7d-486c-85f9-e7ac6e689f4e', type: 'user' }], ], [ 'Hey, [@aleksandar-alex](http://localhost:3000/organization/alex) - this look like you', - [{ id: 'alex', type: 'organization' }], + [{ id: '03bb5b07-f134-4074-97b9-1dd7950c7fa4', type: 'organization' }], ], [ 'Hey, [@aleksandar-alex](https://localhost:3000/organization/alex) - this look like you', - [{ id: 'alex', type: 'organization' }], + [{ id: '03bb5b07-f134-4074-97b9-1dd7950c7fa4', type: 'organization' }], ], [ 'Hey, [@aleksandar](http://localhost:3000/organization/alex-alex) - this look like you', - [{ id: 'alex-alex', type: 'organization' }], + [{ id: '03bb5b07-f134-4074-97b9-1dd7950c7fa4', type: 'organization' }], ], [ 'Hey, [@aleksandar](https://localhost:3000/organization/alex-alex) - this look like you', - [{ id: 'alex-alex', type: 'organization' }], + [{ id: '03bb5b07-f134-4074-97b9-1dd7950c7fa4', type: 'organization' }], ], [ 'Hey, [@aleksandar](http://localhost:3000/user/alex) - this look like you', - [{ id: 'alex', type: 'user' }], + [{ id: 'b69f82a1-bc7d-486c-85f9-e7ac6e689f4e', type: 'user' }], ], [ 'Hey, [@aleksandar](https://localhost:3000/user/alex) - this look like you', - [{ id: 'alex', type: 'user' }], + [{ id: 'b69f82a1-bc7d-486c-85f9-e7ac6e689f4e', type: 'user' }], ], [ 'Hey, [@aleksandar](http://localhost:3000/organization/alex) - this look like you', - [{ id: 'alex', type: 'organization' }], + [{ id: '03bb5b07-f134-4074-97b9-1dd7950c7fa4', type: 'organization' }], ], [ 'Hey, [@aleksandar](https://localhost:3000/organization/alex) - this look like you', - [{ id: 'alex', type: 'organization' }], + [{ id: '03bb5b07-f134-4074-97b9-1dd7950c7fa4', type: 'organization' }], ], [ 'Hey, [@aleksandar](http://localhost:3000/user/alex) - this look like you\n' + 'Hey, [@aleksandar](http://localhost:3000/organization/alex-org) - this look like you', [ - { id: 'alex', type: 'user' }, - { id: 'alex-org', type: 'organization' }, + { id: 'b69f82a1-bc7d-486c-85f9-e7ac6e689f4e', type: 'user' }, + { id: '03bb5b07-f134-4074-97b9-1dd7950c7fa4', type: 'organization' }, ], ], [ 'Hey, [@aleksandar](https://localhost:3000/user/alex) - this look like you\n' + 'Hey, [@aleksandar](https://localhost:3000/organization/alex-org) - this look like you', [ - { id: 'alex', type: 'user' }, - { id: 'alex-org', type: 'organization' }, + { id: 'b69f82a1-bc7d-486c-85f9-e7ac6e689f4e', type: 'user' }, + { id: '03bb5b07-f134-4074-97b9-1dd7950c7fa4', type: 'organization' }, ], ], ])('%s -> %j', async (text, expected) => { - const result = await service.getMentionsFromText(text); + const user = testData.user as IUser; + const organization = testData.organization as any; + const virtualContributor = + testData.virtualContributor as IVirtualContributor; + jest + .spyOn(contributorLookupService, 'getUserByNameIdOrFail') + .mockResolvedValue(user); + + jest + .spyOn(contributorLookupService, 'getOrganizationByNameIdOrFail') + .mockResolvedValue(organization); + + jest + .spyOn(contributorLookupService, 'getVirtualContributorByNameIdOrFail') + .mockResolvedValue(virtualContributor); + + const result = await roomMentionsService.getMentionsFromText(text); expect(result.length).toBe(expected.length); expect(result).toStrictEqual(expected); }); diff --git a/test/data/virtual-contributor.json b/test/data/virtual-contributor.json new file mode 100644 index 0000000000..bb1f34a9cb --- /dev/null +++ b/test/data/virtual-contributor.json @@ -0,0 +1,6 @@ +{ + "virtualContributor": { + "id": "08a43f9f-58e7-4c65-bf38-be283a548b3b", + "nameID": "bridgeuniandbusiness" + } +} diff --git a/test/mocks/contributor.lookup.service.mock.ts b/test/mocks/contributor.lookup.service.mock.ts new file mode 100644 index 0000000000..ea7bbb5f20 --- /dev/null +++ b/test/mocks/contributor.lookup.service.mock.ts @@ -0,0 +1,13 @@ +import { MockValueProvider } from '@test/utils/mock.value.provider'; +import { ConfigService } from '@nestjs/config'; +import { ContributorLookupService } from '@services/infrastructure/contributor-lookup/contributor.lookup.service'; + +export const MockContributorLookupService: MockValueProvider = + { + provide: ConfigService, + useValue: { + getUserByNameIdOrFail: jest.fn(), + getOrganizationByNameIdOrFail: jest.fn(), + getVirtualContributorByNameIdOrFail: jest.fn(), + }, + }; diff --git a/test/utils/test-data.ts b/test/utils/test-data.ts index 416c764862..451bde9f43 100644 --- a/test/utils/test-data.ts +++ b/test/utils/test-data.ts @@ -1,4 +1,5 @@ import * as user from '@test/data/user.json'; +import * as virtualContributor from '@test/data/virtual-contributor.json'; import * as agent from '@test/data/agent.json'; import * as organization from '@test/data/organization.json'; import * as space from '@test/data/space.json'; @@ -18,4 +19,5 @@ export const testData = { ...applications, ...userRoles, ...agentInfo, + ...virtualContributor, }; From 2bebb19892f29b6de315625c36096441d7f6a5d6 Mon Sep 17 00:00:00 2001 From: Valentin Yanakiev Date: Tue, 6 Aug 2024 15:38:32 +0300 Subject: [PATCH 17/27] Refactored me service --- src/services/api/me/me.service.ts | 88 ++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 31 deletions(-) diff --git a/src/services/api/me/me.service.ts b/src/services/api/me/me.service.ts index 29bba8f75d..35c10c2f37 100644 --- a/src/services/api/me/me.service.ts +++ b/src/services/api/me/me.service.ts @@ -146,48 +146,74 @@ export class MeService { const sortedFlatListSpacesWithMembership = await this.getSpaceMembershipsForAgentInfo(agentInfo); - const levelZeroSpaces = sortedFlatListSpacesWithMembership.filter( - space => space.level === SpaceLevel.SPACE + const levelZeroSpaces = this.filterSpacesByLevel( + sortedFlatListSpacesWithMembership, + SpaceLevel.SPACE ); - const levelOneSpaces = sortedFlatListSpacesWithMembership.filter( - space => space.level === SpaceLevel.CHALLENGE + const levelOneSpaces = this.filterSpacesByLevel( + sortedFlatListSpacesWithMembership, + SpaceLevel.CHALLENGE ); - const levelTwoSpaces = sortedFlatListSpacesWithMembership.filter( - space => space.level === SpaceLevel.OPPORTUNITY + const levelTwoSpaces = this.filterSpacesByLevel( + sortedFlatListSpacesWithMembership, + SpaceLevel.OPPORTUNITY ); - const levelZeroMemberships: CommunityMembershipResult[] = []; - for (const levelZeroSpace of levelZeroSpaces) { + + const levelZeroMemberships = levelZeroSpaces.map(levelZeroSpace => { const levelZeroMembership: CommunityMembershipResult = { id: levelZeroSpace.id, space: levelZeroSpace, - childMemberships: [], + childMemberships: this.getChildMemberships( + levelZeroSpace, + levelOneSpaces, + levelTwoSpaces + ), }; - for (const levelOneSpace of levelOneSpaces) { - if (levelOneSpace.parentSpace?.id === levelZeroSpace.id) { - const levelOneMembership: CommunityMembershipResult = { - id: levelOneSpace.id, - space: levelOneSpace, - childMemberships: [], - }; - for (const levelTwoSpace of levelTwoSpaces) { - if (levelTwoSpace.parentSpace?.id === levelOneSpace.id) { - const levelTwoMembership: CommunityMembershipResult = { - id: levelTwoSpace.id, - space: levelTwoSpace, - childMemberships: [], - }; - levelOneMembership.childMemberships.push(levelTwoMembership); - } - } - levelZeroMembership.childMemberships.push(levelOneMembership); - } - } - levelZeroMemberships.push(levelZeroMembership); - } + return levelZeroMembership; + }); return levelZeroMemberships; } + private filterSpacesByLevel(spaces: ISpace[], level: SpaceLevel): ISpace[] { + return spaces.filter(space => space.level === level); + } + + private getChildMemberships( + parentSpace: ISpace, + childSpaces: ISpace[], + grandChildSpaces: ISpace[] + ): CommunityMembershipResult[] { + return childSpaces + .filter(childSpace => childSpace.parentSpace?.id === parentSpace.id) + .map(childSpace => { + const childMembership: CommunityMembershipResult = { + id: childSpace.id, + space: childSpace, + childMemberships: this.getGrandChildMemberships( + childSpace, + grandChildSpaces + ), + }; + return childMembership; + }); + } + + private getGrandChildMemberships( + parentSpace: ISpace, + grandChildSpaces: ISpace[] + ): CommunityMembershipResult[] { + return grandChildSpaces + .filter( + grandChildSpace => grandChildSpace.parentSpace?.id === parentSpace.id + ) + .map(grandChildSpace => ({ + id: grandChildSpace.id, + space: grandChildSpace, + childMemberships: [], + })); + } + // Returns a map of all collaboration IDs with parent space ID private getSpaceMembershipCollaborationInfo( spaces: ISpace[] From 9a69c0adbcc3013cfb554ccdc708dde6b63cca68 Mon Sep 17 00:00:00 2001 From: Valentin Yanakiev Date: Tue, 6 Aug 2024 18:17:21 +0300 Subject: [PATCH 18/27] Address comments --- alkemio.yml | 4 +- src/main.ts | 4 +- .../configuration/config/config.service.ts | 55 +++++++++++++++---- .../storage/file.storage.config.interface.ts | 6 -- src/types/alkemio.config.ts | 6 +- 5 files changed, 50 insertions(+), 25 deletions(-) diff --git a/alkemio.yml b/alkemio.yml index fcc9644c20..288b966636 100644 --- a/alkemio.yml +++ b/alkemio.yml @@ -278,9 +278,9 @@ communications: ## storage ## # Alkemio uses multiple types of persistent storage, including SQL database and IPFS. storage: - graphql_upload: + file: # 20MB - max_file_size: 1048576 + max_file_size: 2097152 # MySQL database configuration for usage by the Alkemio Server. # The authentication method used by Alkemio Server is MySQL Native Password. # Note: both schema / database name are used for configuration and they need to have the same value. diff --git a/src/main.ts b/src/main.ts index 900925cdef..ecf6dd2c3d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -56,9 +56,9 @@ const bootstrap = async () => { app.use( graphqlUploadExpress({ - maxFileSize: configService.get('storage.graphql_upload.max_file_size', { + maxFileSize: configService.get('storage.file.max_file_size', { infer: true, - }) + }), }) ); diff --git a/src/platform/configuration/config/config.service.ts b/src/platform/configuration/config/config.service.ts index da99796cf9..bdf53b9479 100644 --- a/src/platform/configuration/config/config.service.ts +++ b/src/platform/configuration/config/config.service.ts @@ -15,8 +15,15 @@ export class KonfigService { this.configService.get('hosting.endpoint_cluster', { infer: true }) ).hostname; - const { sentry, apm } = this.configService.get('monitoring', { infer: true }); - const geoConfig = this.configService.get('integrations.geo', { infer: true }); + const { sentry, apm } = this.configService.get('monitoring', { + infer: true, + }); + const geoConfig = this.configService.get('integrations.geo', { + infer: true, + }); + const fileConfig = this.configService.get('storage.file', { + infer: true, + }); const platform = this.configService.get('platform', { infer: true }); return { authentication: { @@ -29,36 +36,53 @@ export class KonfigService { }, { name: PlatformFeatureFlagName.COMMUNICATIONS, - enabled: this.configService.get('communications.enabled', { infer: true }), + enabled: this.configService.get('communications.enabled', { + infer: true, + }), }, { name: PlatformFeatureFlagName.COMMUNICATIONS_DISCUSSIONS, - enabled: this.configService.get('communications.discussions.enabled', { infer: true }), + enabled: this.configService.get( + 'communications.discussions.enabled', + { infer: true } + ), }, { name: PlatformFeatureFlagName.SUBSCRIPTIONS, - enabled: this.configService.get('hosting.subscriptions.enabled', { infer: true }), + enabled: this.configService.get('hosting.subscriptions.enabled', { + infer: true, + }), }, { name: PlatformFeatureFlagName.NOTIFICATIONS, - enabled: this.configService.get('notifications.enabled', { infer: true }), + enabled: this.configService.get('notifications.enabled', { + infer: true, + }), }, { name: PlatformFeatureFlagName.WHITEBOARDS, - enabled: this.configService.get('collaboration.whiteboards.enabled', { infer: true }), + enabled: this.configService.get('collaboration.whiteboards.enabled', { + infer: true, + }), }, { name: PlatformFeatureFlagName.LANDING_PAGE, - enabled: this.configService.get('platform.landing_page.enabled', { infer: true }), + enabled: this.configService.get('platform.landing_page.enabled', { + infer: true, + }), }, { name: PlatformFeatureFlagName.GUIDENCE_ENGINE, - enabled: this.configService.get('platform.guidance_engine.enabled', { infer: true }), + enabled: this.configService.get('platform.guidance_engine.enabled', { + infer: true, + }), }, ], locations: { domain, - environment: this.configService.get('hosting.environment', { infer: true }), + environment: this.configService.get('hosting.environment', { + infer: true, + }), terms: platform.terms, privacy: platform.privacy, security: platform.security, @@ -94,6 +118,11 @@ export class KonfigService { geo: { endpoint: geoConfig?.rest_endpoint, }, + storage: { + file: { + maxFileSize: fileConfig?.max_file_size, + }, + }, }; } @@ -112,8 +141,10 @@ export class KonfigService { } async getOryConfig(): Promise { - const oryConfig = - this.configService.get('identity.authentication.providers.ory', { infer: true }); + const oryConfig = this.configService.get( + 'identity.authentication.providers.ory', + { infer: true } + ); return { kratosPublicBaseURL: oryConfig.kratos_public_base_url, issuer: oryConfig.issuer, diff --git a/src/platform/configuration/config/storage/file.storage.config.interface.ts b/src/platform/configuration/config/storage/file.storage.config.interface.ts index f0c254a493..6803ad9db8 100644 --- a/src/platform/configuration/config/storage/file.storage.config.interface.ts +++ b/src/platform/configuration/config/storage/file.storage.config.interface.ts @@ -7,10 +7,4 @@ export abstract class IFileStorageConfig { description: 'Max file size, in bytes.', }) maxFileSize!: number; - - @Field(() => [String], { - nullable: false, - description: 'Allowed mime types for file upload, separated by a coma.', - }) - mimeTypes!: string[]; } diff --git a/src/types/alkemio.config.ts b/src/types/alkemio.config.ts index d6b45505a9..b840af45f4 100644 --- a/src/types/alkemio.config.ts +++ b/src/types/alkemio.config.ts @@ -97,9 +97,9 @@ export type AlkemioConfig = { }; }; storage: { - graphql_upload: { + file: { max_file_size: number; - }, + }; database: { host: string; port: number; @@ -201,7 +201,7 @@ export type AlkemioConfig = { vector_db: { host: string; port: number; - } + }; }; ssi: { enabled: boolean; From a78fb3b06da473e29381ce5452109c38ad1ed7fc Mon Sep 17 00:00:00 2001 From: Valentin Yanakiev Date: Wed, 7 Aug 2024 10:52:50 +0300 Subject: [PATCH 19/27] filter out orphans for contributions --- package-lock.json | 4 ++-- package.json | 2 +- src/services/api/me/me.service.ts | 38 ++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1761e1a26f..e238658aa8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "alkemio-server", - "version": "0.86.0", + "version": "0.86.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "alkemio-server", - "version": "0.86.0", + "version": "0.86.1", "license": "EUPL-1.2", "dependencies": { "@alkemio/matrix-adapter-lib": "^0.4.1", diff --git a/package.json b/package.json index 1449d0056c..a1b1a2ac9f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "alkemio-server", - "version": "0.86.0", + "version": "0.86.1", "description": "Alkemio server, responsible for managing the shared Alkemio platform", "author": "Alkemio Foundation", "private": false, diff --git a/src/services/api/me/me.service.ts b/src/services/api/me/me.service.ts index 29bba8f75d..d4660be383 100644 --- a/src/services/api/me/me.service.ts +++ b/src/services/api/me/me.service.ts @@ -12,10 +12,7 @@ import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { sortSpacesByActivity } from '@domain/space/space/sort.spaces.by.activity'; import { CommunityInvitationResult } from './dto/me.invitation.result'; import { CommunityResolverService } from '@services/infrastructure/entity-resolver/community.resolver.service'; -import { - EntityNotFoundException, - RelationshipNotFoundException, -} from '@common/exceptions'; +import { EntityNotFoundException } from '@common/exceptions'; import { CommunityApplicationResult } from './dto/me.application.result'; import { ContributorService } from '@domain/community/contributor/contributor.service'; import { UserService } from '@domain/community/user/user.service'; @@ -101,25 +98,40 @@ export class MeService { const spaceIds = Array.from(credentialMap.get('spaces')?.keys() ?? []); const allSpaces = await this.spaceService.getSpacesInList(spaceIds); + const validSpaces = this.filterValidSpaces(allSpaces); + const spaceMembershipCollaborationInfo = + this.getSpaceMembershipCollaborationInfo(validSpaces); + const latestActivitiesPerSpace = + await this.activityService.getLatestActivitiesPerSpaceMembership( + agentInfo.userID, + spaceMembershipCollaborationInfo + ); + return sortSpacesByActivity(validSpaces, latestActivitiesPerSpace); + } + + /** + * Function that returns all spaces that are valid (L1 and L2 spaces have parents) + * @param allSpaces all spaces to be filtered out + * @returns spaces that are valid (L1 and L2 spaces have parents). + * Orphaned spaces are logged as warnings and filtered out, also spaces without collaboration are filtered out. + */ + private filterValidSpaces(allSpaces: ISpace[]) { + const validSpaces = []; + for (const space of allSpaces) { if ( (space.level !== SpaceLevel.SPACE && !space.parentSpace) || !space.collaboration ) { - throw new RelationshipNotFoundException( + this.logger.warn( `Space ${space.id} is missing parent space or collaboration`, LogContext.COMMUNITY ); + } else { + validSpaces.push(space); } } - const spaceMembershipCollaborationInfo = - this.getSpaceMembershipCollaborationInfo(allSpaces); - const latestActivitiesPerSpace = - await this.activityService.getLatestActivitiesPerSpaceMembership( - agentInfo.userID, - spaceMembershipCollaborationInfo - ); - return sortSpacesByActivity(allSpaces, latestActivitiesPerSpace); + return validSpaces; } public async getSpaceMembershipsFlat( From 0a2db8da4e2b803fbd0d97d09d486c0ad9bf1e28 Mon Sep 17 00:00:00 2001 From: Neil Smyth Date: Wed, 7 Aug 2024 15:24:43 +0100 Subject: [PATCH 20/27] fixed default me query for playground --- src/config/graphql/me.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/config/graphql/me.ts b/src/config/graphql/me.ts index 7e63959ad0..227f6a81f9 100644 --- a/src/config/graphql/me.ts +++ b/src/config/graphql/me.ts @@ -17,8 +17,11 @@ export const meQuery = gql` } } } - spaceMemberships { - nameID + spaceMembershipsFlat { + space { + nameID + level + } } } } From 1ff12626bbdb907a90097b8301208769a6d6591f Mon Sep 17 00:00:00 2001 From: Carlos Cano Date: Thu, 8 Aug 2024 08:30:13 +0200 Subject: [PATCH 21/27] Organization account tab (#4370) Co-authored-by: Bobby Kolev --- src/domain/space/account/account.resolver.fields.ts | 6 +++--- src/domain/space/account/account.resolver.mutations.ts | 6 ++++++ src/domain/space/account/account.service.ts | 8 +------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/domain/space/account/account.resolver.fields.ts b/src/domain/space/account/account.resolver.fields.ts index 902d836003..7d8125b6ed 100644 --- a/src/domain/space/account/account.resolver.fields.ts +++ b/src/domain/space/account/account.resolver.fields.ts @@ -127,12 +127,12 @@ export class AccountResolverFields { } @ResolveField('spaceID', () => String, { - nullable: false, + nullable: true, description: 'The ID for the root space for the Account .', }) - async spaceID(@Parent() account: Account): Promise { + async spaceID(@Parent() account: Account): Promise { const space = await this.accountService.getRootSpace(account); - return space.id; + return space?.id; } @ResolveField('authorization', () => IAuthorizationPolicy, { diff --git a/src/domain/space/account/account.resolver.mutations.ts b/src/domain/space/account/account.resolver.mutations.ts index f4ca5778fe..5dd2326c8c 100644 --- a/src/domain/space/account/account.resolver.mutations.ts +++ b/src/domain/space/account/account.resolver.mutations.ts @@ -106,6 +106,12 @@ export class AccountResolverMutations { community: true, }, }); + if (!rootSpace) { + throw new EntityNotInitializedException( + `Unable to load root space for account ${account.id}`, + LogContext.ACCOUNT + ); + } await this.namingReporter.createOrUpdateName( rootSpace.id, diff --git a/src/domain/space/account/account.service.ts b/src/domain/space/account/account.service.ts index d54d666ab6..d627752ea0 100644 --- a/src/domain/space/account/account.service.ts +++ b/src/domain/space/account/account.service.ts @@ -381,7 +381,7 @@ export class AccountService { async getRootSpace( accountInput: IAccount, options?: FindOneOptions - ): Promise { + ): Promise { if (accountInput.space && accountInput.space.profile) { return accountInput.space; } @@ -393,12 +393,6 @@ export class AccountService { }, }, }); - if (!account.space) { - throw new EntityNotFoundException( - `Unable to find space for account: ${accountInput.id}`, - LogContext.ACCOUNT - ); - } return account.space; } From dbc7d90112e6dca72cf6bd3815b4a9665efbec31 Mon Sep 17 00:00:00 2001 From: Valentin Yanakiev Date: Thu, 8 Aug 2024 10:08:33 +0300 Subject: [PATCH 22/27] Fix logging message --- src/domain/space/account/account.resolver.mutations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/space/account/account.resolver.mutations.ts b/src/domain/space/account/account.resolver.mutations.ts index 5dd2326c8c..de801a935e 100644 --- a/src/domain/space/account/account.resolver.mutations.ts +++ b/src/domain/space/account/account.resolver.mutations.ts @@ -78,7 +78,7 @@ export class AccountResolverMutations { agentInfo, authorizationPolicy, AuthorizationPrivilege.CREATE_SPACE, - `create account with space: ${accountData}` + `create account with hostID: ${accountData.hostID}` ); let account = await this.accountService.createAccount(accountData); From dfbf43866aeca92feafe7614e77ae6403d898b7e Mon Sep 17 00:00:00 2001 From: Svetoslav Petkov Date: Thu, 8 Aug 2024 12:26:17 +0300 Subject: [PATCH 23/27] Atomic space creation (#4330) * community * context * tagset & visual * wip * wip * wip * wip * some code refactored --------- Co-authored-by: Valentin Yanakiev --- src/config/winston.config.ts | 16 ++- .../agent.info.cache.service.ts | 5 +- .../authentication/authentication.service.ts | 21 +++- src/core/authentication/ory.api.strategy.ts | 10 +- src/core/authentication/ory.strategy.ts | 16 +-- src/core/bootstrap/bootstrap.service.ts | 15 ++- .../auth.reset.service.factory.ts | 4 +- .../matrix.adapter.service.factory.ts | 4 +- .../notifications.service.factory.ts | 4 +- .../microservices/subscription.factory.ts | 4 +- ...ngine.community.manager.service.factory.ts | 5 +- ...ntributor.engine.expert.service.factory.ts | 4 +- ...ributor.engine.guidance.service.factory.ts | 4 +- .../wallet-manager.service.factory.ts | 4 +- .../middleware/request.logger.middleware.ts | 10 +- .../middleware/session.extend.middleware.ts | 15 ++- src/domain/agent/agent/agent.service.ts | 19 ++- .../callout.framing.service.ts | 9 ++ .../collaboration/callout/callout.service.ts | 58 ++++----- .../collaboration/collaboration.service.ts | 111 ++++++++++++------ .../innovation-flow/innovaton.flow.service.ts | 4 +- src/domain/common/form/form.service.ts | 4 +- .../tagset.template.set.service.ts | 22 ++-- .../tagset.template.service.ts | 13 +- .../communication/communication.service.ts | 2 +- .../community.guidelines.service.ts | 4 +- .../community.policy.service.ts | 15 ++- .../community/community/community.service.ts | 27 +++-- .../actor-group/actor-group.service.ts | 18 +-- src/domain/context/context/context.service.ts | 16 ++- .../ecosystem-model.service.ts | 25 ++-- src/domain/space/account/account.service.ts | 3 +- .../space.defaults/space.defaults.service.ts | 39 ++++-- src/domain/space/space/space.service.ts | 70 +++++------ .../storage/document/document.service.ts | 5 +- .../innovation.flow.template.service.ts | 4 +- .../timeline/calendar/calendar.service.ts | 4 +- .../timeline/timeline/timeline.service.ts | 6 +- .../adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts | 4 +- .../local-storage/local.storage.adapter.ts | 5 +- .../ai-server/ai-server/ai.server.service.ts | 9 +- .../chat-guidance/chat.guidance.service.ts | 4 +- .../api/search/v1/search.resolver.queries.ts | 4 +- .../v2/extract/search.extract.service.ts | 5 +- .../api/search/v2/ingest/get.index.pattern.ts | 6 +- .../contribution.reporter.service.ts | 8 +- .../elasticsearch.client.factory.ts | 4 +- .../guidance.reporter.service.ts | 8 +- .../name-reporter/name.reporter.service.ts | 8 +- ...xcalidraw.redis.server.factory.provider.ts | 5 +- .../excalidraw-backend/excalidraw.server.ts | 5 +- .../utils/get.excalidraw.base.server.ts | 5 +- .../geo-location/geo.location.service.spec.ts | 12 +- .../trust.registry.adapter.ts | 5 +- .../event-bus/event.bus.module.ts | 5 +- .../url-generator/url.generator.service.ts | 4 +- .../whiteboard.integration.service.ts | 10 +- 57 files changed, 448 insertions(+), 287 deletions(-) diff --git a/src/config/winston.config.ts b/src/config/winston.config.ts index f5e24b6ea8..d2c690bb99 100644 --- a/src/config/winston.config.ts +++ b/src/config/winston.config.ts @@ -27,7 +27,10 @@ export class WinstonConfigService { constructor(private configService: ConfigService) {} async createWinstonModuleOptions() { - const consoleEnabled: boolean = this.configService.get('monitoring.logging.console_logging_enabled', { infer: true }); + const consoleEnabled: boolean = this.configService.get( + 'monitoring.logging.console_logging_enabled', + { infer: true } + ); const transports: any[] = [ new winston.transports.Console({ @@ -38,12 +41,16 @@ export class WinstonConfigService { : consoleLoggingStandardFormat) ), level: this.configService - .get('monitoring.logging.level', { infer: true }).toLowerCase(), + .get('monitoring.logging.level', { infer: true }) + .toLowerCase(), silent: !consoleEnabled, }), ]; - const contextToFileConfig = this.configService.get('monitoring.logging.context_to_file', { infer: true }); + const contextToFileConfig = this.configService.get( + 'monitoring.logging.context_to_file', + { infer: true } + ); if (contextToFileConfig.enabled) { const filename = contextToFileConfig.filename; @@ -78,7 +85,8 @@ export class WinstonConfigService { const fileTransportOptions: FileTransportOptions = { format: myFormat, level: this.configService - .get('monitoring.logging.level', { infer: true }).toLowerCase(), + .get('monitoring.logging.level', { infer: true }) + .toLowerCase(), silent: false, filename: filename, }; diff --git a/src/core/authentication.agent.info/agent.info.cache.service.ts b/src/core/authentication.agent.info/agent.info.cache.service.ts index f06039a3a6..345346de58 100644 --- a/src/core/authentication.agent.info/agent.info.cache.service.ts +++ b/src/core/authentication.agent.info/agent.info.cache.service.ts @@ -25,7 +25,10 @@ export class AgentInfoCacheService { @InjectEntityManager('default') private entityManager: EntityManager ) { - this.cache_ttl = this.configService.get('identity.authentication.cache_ttl', { infer: true }); + this.cache_ttl = this.configService.get( + 'identity.authentication.cache_ttl', + { infer: true } + ); } public async getAgentInfoFromCache( diff --git a/src/core/authentication/authentication.service.ts b/src/core/authentication/authentication.service.ts index d11334e32d..34e064be6b 100644 --- a/src/core/authentication/authentication.service.ts +++ b/src/core/authentication/authentication.service.ts @@ -1,6 +1,11 @@ import { ConfigService } from '@nestjs/config'; import { Inject, Injectable, LoggerService } from '@nestjs/common'; -import { Configuration, FrontendApi, IdentityApi, Session } from '@ory/kratos-client'; +import { + Configuration, + FrontendApi, + IdentityApi, + Session, +} from '@ory/kratos-client'; import { LogContext } from '@common/enums'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { UserService } from '@domain/community/user/user.service'; @@ -25,7 +30,6 @@ export class AuthenticationService { private readonly kratosIdentityClient: IdentityApi; private readonly kratosFrontEndClient: FrontendApi; - constructor( private agentCacheService: AgentInfoCacheService, private configService: ConfigService, @@ -33,15 +37,20 @@ export class AuthenticationService { private agentService: AgentService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { - this.kratosPublicUrlServer = this.configService.get('identity.authentication.providers.ory.kratos_public_base_url_server', { infer: true }); + this.kratosPublicUrlServer = this.configService.get( + 'identity.authentication.providers.ory.kratos_public_base_url_server', + { infer: true } + ); const { kratos_public_base_url_server, kratos_admin_base_url_server, admin_service_account, - earliest_possible_extend - } = this.configService.get('identity.authentication.providers.ory', { infer: true }); + earliest_possible_extend, + } = this.configService.get('identity.authentication.providers.ory', { + infer: true, + }); this.kratosPublicUrlServer = kratos_public_base_url_server; - const kratosAdminUrlServer = kratos_admin_base_url_server + const kratosAdminUrlServer = kratos_admin_base_url_server; this.adminPasswordIdentifier = admin_service_account.username; this.adminPassword = admin_service_account.password; diff --git a/src/core/authentication/ory.api.strategy.ts b/src/core/authentication/ory.api.strategy.ts index f0eee0ca82..afe0ff38c4 100644 --- a/src/core/authentication/ory.api.strategy.ts +++ b/src/core/authentication/ory.api.strategy.ts @@ -25,7 +25,10 @@ export class OryApiStrategy extends PassportStrategy( ) { super(); - const kratosPublicBaseUrl = this.configService.get('identity.authentication.providers.ory.kratos_public_base_url_server', { infer: true }); + const kratosPublicBaseUrl = this.configService.get( + 'identity.authentication.providers.ory.kratos_public_base_url_server', + { infer: true } + ); this.kratosClient = new FrontendApi( new Configuration({ @@ -35,7 +38,10 @@ export class OryApiStrategy extends PassportStrategy( } async validate(payload: IncomingMessage) { - const apiAccessEnabled = this.configService.get('identity.authentication.api_access_enabled', { infer: true }); + const apiAccessEnabled = this.configService.get( + 'identity.authentication.api_access_enabled', + { infer: true } + ); if (!apiAccessEnabled) { throw new ApiRestrictedAccessException('API access is restricted!'); diff --git a/src/core/authentication/ory.strategy.ts b/src/core/authentication/ory.strategy.ts index 11eae7ac65..2d12c2d5a9 100644 --- a/src/core/authentication/ory.strategy.ts +++ b/src/core/authentication/ory.strategy.ts @@ -1,7 +1,4 @@ -import { - AlkemioErrorStatus, - LogContext, -} from '@common/enums'; +import { AlkemioErrorStatus, LogContext } from '@common/enums'; import { Inject, Injectable, LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config/dist'; import { PassportStrategy } from '@nestjs/passport'; @@ -23,15 +20,20 @@ export class OryStrategy extends PassportStrategy(Strategy, 'oathkeeper-jwt') { private readonly authService: AuthenticationService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { - super({ secretOrKeyProvider: passportJwtSecret({ cache: true, rateLimit: true, jwksRequestsPerMinute: 5, - jwksUri: configService.get('identity.authentication.providers.ory.jwks_uri', { infer: true }), + jwksUri: configService.get( + 'identity.authentication.providers.ory.jwks_uri', + { infer: true } + ), }), - issuer: configService.get('identity.authentication.providers.ory.issuer', { infer: true }), + issuer: configService.get( + 'identity.authentication.providers.ory.issuer', + { infer: true } + ), jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ignoreExpiration: true, }); diff --git a/src/core/bootstrap/bootstrap.service.ts b/src/core/bootstrap/bootstrap.service.ts index cdfb9ead94..960e84b7cc 100644 --- a/src/core/bootstrap/bootstrap.service.ts +++ b/src/core/bootstrap/bootstrap.service.ts @@ -66,7 +66,10 @@ export class BootstrapService { this.logger.verbose?.('Bootstrapping...', LogContext.BOOTSTRAP); Profiling.logger = this.logger; - const profilingEnabled = this.configService.get('monitoring.logging.profiling_enabled', { infer: true }); + const profilingEnabled = this.configService.get( + 'monitoring.logging.profiling_enabled', + { infer: true } + ); if (profilingEnabled) { Profiling.profilingEnabled = profilingEnabled; } @@ -89,7 +92,10 @@ export class BootstrapService { } async bootstrapProfiles() { - const bootstrapAuthorizationEnabled = this.configService.get('bootstrap.authorization.enabled', { infer: true }); + const bootstrapAuthorizationEnabled = this.configService.get( + 'bootstrap.authorization.enabled', + { infer: true } + ); if (!bootstrapAuthorizationEnabled) { this.logger.verbose?.( `Authorization Profile Loading: ${bootstrapAuthorizationEnabled}`, @@ -98,7 +104,10 @@ export class BootstrapService { return; } - const bootstrapFilePath = this.configService.get('bootstrap.authorization.file', { infer: true }); + const bootstrapFilePath = this.configService.get( + 'bootstrap.authorization.file', + { infer: true } + ); let bootstrapJson = { ...defaultRoles, diff --git a/src/core/microservices/auth.reset.service.factory.ts b/src/core/microservices/auth.reset.service.factory.ts index e023f43c29..e7a680bee0 100644 --- a/src/core/microservices/auth.reset.service.factory.ts +++ b/src/core/microservices/auth.reset.service.factory.ts @@ -9,7 +9,9 @@ export async function authResetServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService?.get('microservices.rabbitmq', { infer: true }); + const rabbitMqOptions = configService?.get('microservices.rabbitmq', { + infer: true, + }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/core/microservices/matrix.adapter.service.factory.ts b/src/core/microservices/matrix.adapter.service.factory.ts index 77310c89bb..be88635851 100644 --- a/src/core/microservices/matrix.adapter.service.factory.ts +++ b/src/core/microservices/matrix.adapter.service.factory.ts @@ -9,7 +9,9 @@ export async function matrixAdapterServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService.get('microservices.rabbitmq', { infer: true }); + const rabbitMqOptions = configService.get('microservices.rabbitmq', { + infer: true, + }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/core/microservices/notifications.service.factory.ts b/src/core/microservices/notifications.service.factory.ts index 1e631208c8..0319fb0b9c 100644 --- a/src/core/microservices/notifications.service.factory.ts +++ b/src/core/microservices/notifications.service.factory.ts @@ -9,7 +9,9 @@ export async function notificationsServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService?.get('microservices.rabbitmq', { infer: true }); + const rabbitMqOptions = configService?.get('microservices.rabbitmq', { + infer: true, + }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/core/microservices/subscription.factory.ts b/src/core/microservices/subscription.factory.ts index 1f752a1832..6db3b5efea 100644 --- a/src/core/microservices/subscription.factory.ts +++ b/src/core/microservices/subscription.factory.ts @@ -12,7 +12,9 @@ export async function subscriptionFactory( exchangeName: string, queueName: string ): Promise { - const rabbitMqOptions = configService?.get('microservices.rabbitmq', { infer: true }); + const rabbitMqOptions = configService?.get('microservices.rabbitmq', { + infer: true, + }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; diff --git a/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts b/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts index 2b33526e98..4c2f4cedd0 100644 --- a/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts +++ b/src/core/microservices/virtual.contributor.engine.community.manager.service.factory.ts @@ -9,7 +9,10 @@ export async function virtualContributorEngineCommunityManagerServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const connectionOptions = configService.get('microservices.rabbitmq.connection', { infer: true }); + const connectionOptions = configService.get( + 'microservices.rabbitmq.connection', + { infer: true } + ); const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { const options = { diff --git a/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts b/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts index 9757397601..7ab03b8943 100644 --- a/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts +++ b/src/core/microservices/virtual.contributor.engine.expert.service.factory.ts @@ -9,7 +9,9 @@ export async function virtualContributorEngineExpertServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService.get('microservices.rabbitmq', { infer: true }); + const rabbitMqOptions = configService.get('microservices.rabbitmq', { + infer: true, + }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts b/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts index dbcab15196..e07c590a6b 100644 --- a/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts +++ b/src/core/microservices/virtual.contributor.engine.guidance.service.factory.ts @@ -9,7 +9,9 @@ export async function virtualContributorEngineGuidanceServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService.get('microservices.rabbitmq', { infer: true }); + const rabbitMqOptions = configService.get('microservices.rabbitmq', { + infer: true, + }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/core/microservices/wallet-manager.service.factory.ts b/src/core/microservices/wallet-manager.service.factory.ts index 36a6f3f4c9..15d943b935 100644 --- a/src/core/microservices/wallet-manager.service.factory.ts +++ b/src/core/microservices/wallet-manager.service.factory.ts @@ -9,7 +9,9 @@ export async function walletManagerServiceFactory( logger: LoggerService, configService: ConfigService ): Promise { - const rabbitMqOptions = configService.get('microservices.rabbitmq', { infer: true }); + const rabbitMqOptions = configService.get('microservices.rabbitmq', { + infer: true, + }); const connectionOptions = rabbitMqOptions.connection; const connectionString = `amqp://${connectionOptions.user}:${connectionOptions.password}@${connectionOptions.host}:${connectionOptions.port}?heartbeat=30`; try { diff --git a/src/core/middleware/request.logger.middleware.ts b/src/core/middleware/request.logger.middleware.ts index 1a1569aa4d..4bb739e84c 100644 --- a/src/core/middleware/request.logger.middleware.ts +++ b/src/core/middleware/request.logger.middleware.ts @@ -19,11 +19,17 @@ export class RequestLoggerMiddleware implements NestMiddleware { private readonly configService: ConfigService, @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) { - const reqLoggingConfig = this.configService.get('monitoring.logging.requests', { infer: true }); + const reqLoggingConfig = this.configService.get( + 'monitoring.logging.requests', + { infer: true } + ); this.requestFullLogging = reqLoggingConfig?.full_logging_enabled; this.requestHeadersLogging = reqLoggingConfig?.headers_logging_enabled; - const resLoggingConfig = this.configService.get('monitoring.logging.responses', { infer: true }); + const resLoggingConfig = this.configService.get( + 'monitoring.logging.responses', + { infer: true } + ); this.responseHeadersLogging = resLoggingConfig?.headers_logging_enabled; } diff --git a/src/core/middleware/session.extend.middleware.ts b/src/core/middleware/session.extend.middleware.ts index babf5fa169..44fb31f226 100644 --- a/src/core/middleware/session.extend.middleware.ts +++ b/src/core/middleware/session.extend.middleware.ts @@ -24,11 +24,20 @@ export class SessionExtendMiddleware implements NestMiddleware { private readonly authService: AuthenticationService, private readonly configService: ConfigService ) { - this.SESSION_COOKIE_NAME = this.configService.get('identity.authentication.providers.ory.session_cookie_name', { infer: true }); + this.SESSION_COOKIE_NAME = this.configService.get( + 'identity.authentication.providers.ory.session_cookie_name', + { infer: true } + ); - this.enabled = this.configService.get('identity.authentication.providers.ory.session_cookie_name', { infer: true }); + this.enabled = this.configService.get( + 'identity.authentication.providers.ory.session_cookie_name', + { infer: true } + ); - const kratosPublicBaseUrl = this.configService.get('identity.authentication.providers.ory.kratos_public_base_url_server', { infer: true }); + const kratosPublicBaseUrl = this.configService.get( + 'identity.authentication.providers.ory.kratos_public_base_url_server', + { infer: true } + ); this.kratosClient = new FrontendApi( new Configuration({ diff --git a/src/domain/agent/agent/agent.service.ts b/src/domain/agent/agent/agent.service.ts index 2267293852..e7d96a700f 100644 --- a/src/domain/agent/agent/agent.service.ts +++ b/src/domain/agent/agent/agent.service.ts @@ -69,10 +69,13 @@ export class AgentService { @Inject(SUBSCRIPTION_PROFILE_VERIFIED_CREDENTIAL) private subscriptionVerifiedCredentials: PubSubEngine ) { - this.cache_ttl = this.configService.get('identity.authentication.cache_ttl', { infer: true }); + this.cache_ttl = this.configService.get( + 'identity.authentication.cache_ttl', + { infer: true } + ); } - async createAgent(inputData: CreateAgentInput): Promise { + public async createAgent(inputData: CreateAgentInput): Promise { const agent: IAgent = Agent.create(inputData); agent.credentials = []; agent.authorization = new AuthorizationPolicy(); @@ -80,10 +83,10 @@ export class AgentService { const ssiEnabled = this.configService.get('ssi.enabled', { infer: true }); if (ssiEnabled) { - return await this.createDidOnAgent(agent); + return this.createDidOnAgent(agent); } - return await this.saveAgent(agent); + return agent; } async getAgentOrFail( @@ -255,7 +258,8 @@ export class AgentService { agent.password = Math.random().toString(36).substr(2, 10); agent.did = await this.walletManagerAdapter.createIdentity(agent.password); - return await this.saveAgent(agent); + + return agent; } async getVerifiedCredentials( @@ -550,7 +554,10 @@ export class AgentService { } validateTrustedIssuerOrFail(vcName: string, vcToBeStored: any) { - const trustedIssuerValidationEnabled = this.configService.get('ssi.issuer_validation_enabled', { infer: true }); + const trustedIssuerValidationEnabled = this.configService.get( + 'ssi.issuer_validation_enabled', + { infer: true } + ); if (!trustedIssuerValidationEnabled) return; const trustedIssuers = diff --git a/src/domain/collaboration/callout-framing/callout.framing.service.ts b/src/domain/collaboration/callout-framing/callout.framing.service.ts index ce5c92b3ba..62f6f12834 100644 --- a/src/domain/collaboration/callout-framing/callout.framing.service.ts +++ b/src/domain/collaboration/callout-framing/callout.framing.service.ts @@ -227,6 +227,15 @@ export class CalloutFramingService { public createCalloutFramingInputFromCalloutFraming( calloutFraming: ICalloutFraming ): CreateCalloutFramingInput { + if (!calloutFraming.profile || !calloutFraming.whiteboard) { + throw new EntityNotFoundException( + `CalloutFraming not fully initialised`, + LogContext.COLLABORATION, { + cause: 'Relation for callout framing not loaded', + calloutFramingId: calloutFraming.id, + } + ); + } return { profile: this.profileService.createProfileInputFromProfile( calloutFraming.profile diff --git a/src/domain/collaboration/callout/callout.service.ts b/src/domain/collaboration/callout/callout.service.ts index 36015f800b..4ce9cc5ff9 100644 --- a/src/domain/collaboration/callout/callout.service.ts +++ b/src/domain/collaboration/callout/callout.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { FindOneOptions, FindOptionsRelations, Repository } from 'typeorm'; +import { FindManyOptions, FindOneOptions, FindOptionsRelations, Repository } from 'typeorm'; import { EntityNotFoundException, EntityNotInitializedException, @@ -301,45 +301,47 @@ export class CalloutService { return result; } - public async createCalloutInputFromCallout( + public getCallouts(options: FindManyOptions): Promise { + return this.calloutRepository.find(options); + } + + public createCalloutInputFromCallout( calloutInput: ICallout - ): Promise { - const callout = await this.getCalloutOrFail(calloutInput.id, { - relations: { - contributionDefaults: true, - contributionPolicy: true, - framing: { - profile: { - references: true, - location: true, - tagsets: true, - }, - whiteboard: { - profile: true, - }, - }, - }, - }); - const calloutGroupTagset = - await this.calloutFramingService.getCalloutGroupTagset(callout.framing); + ): CreateCalloutInput { + if ( + !calloutInput.framing + || !calloutInput.contributionDefaults + || !calloutInput.contributionPolicy + ) { + throw new EntityNotInitializedException( + 'Missing callout relation', + LogContext.COLLABORATION, + { + cause: 'Relation for Callout not loaded', + calloutId: calloutInput.id, + } + ); + } + + const calloutGroupTagset = this.calloutFramingService.getCalloutGroupTagset(calloutInput.framing); return { - nameID: callout.nameID, - type: callout.type, - visibility: callout.visibility, + nameID: calloutInput.nameID, + type: calloutInput.type, + visibility: calloutInput.visibility, groupName: calloutGroupTagset.tags[0], framing: this.calloutFramingService.createCalloutFramingInputFromCalloutFraming( - callout.framing + calloutInput.framing ), contributionDefaults: this.contributionDefaultsService.createCalloutContributionDefaultsInputFromCalloutContributionDefaults( - callout.contributionDefaults + calloutInput.contributionDefaults ), contributionPolicy: this.contributionPolicyService.createCalloutContributionPolicyInputFromCalloutContributionPolicy( - callout.contributionPolicy + calloutInput.contributionPolicy ), - sortOrder: callout.sortOrder, + sortOrder: calloutInput.sortOrder, }; } diff --git a/src/domain/collaboration/collaboration/collaboration.service.ts b/src/domain/collaboration/collaboration/collaboration.service.ts index ccb3548e5c..d3bc18d553 100644 --- a/src/domain/collaboration/collaboration/collaboration.service.ts +++ b/src/domain/collaboration/collaboration/collaboration.service.ts @@ -1,6 +1,12 @@ import { Injectable } from '@nestjs/common'; import { InjectEntityManager, InjectRepository } from '@nestjs/typeorm'; -import { EntityManager, FindOneOptions, Repository } from 'typeorm'; +import { + EntityManager, + FindOneOptions, + FindOptionsRelations, + In, + Repository, +} from 'typeorm'; import { EntityNotFoundException, EntityNotInitializedException, @@ -54,6 +60,7 @@ import { IAccount } from '@domain/space/account/account.interface'; import { SpaceType } from '@common/enums/space.type'; import { CalloutGroupName } from '@common/enums/callout.group.name'; import { SpaceLevel } from '@common/enums/space.level'; +import { Callout } from '@domain/collaboration/callout'; @Injectable() export class CollaborationService { @@ -85,13 +92,13 @@ export class CollaborationService { collaboration.authorization = new AuthorizationPolicy(); collaboration.relations = []; collaboration.callouts = []; - collaboration.timeline = await this.timelineService.createTimeline(); + collaboration.timeline = this.timelineService.createTimeline(); const calloutGroups = this.spaceDefaultsService.getCalloutGroups(spaceType); collaboration.groupsStr = this.calloutGroupsService.serializeGroups(calloutGroups); collaboration.tagsetTemplateSet = - await this.tagsetTemplateSetService.createTagsetTemplateSet(); + this.tagsetTemplateSetService.createTagsetTemplateSet(); // Rely on the logic in Space Defaults to create the right innovation flow input const innovationFlowInput = @@ -112,7 +119,7 @@ export class CollaborationService { allowedStates.length > 0 ? allowedStates[0] : undefined, }; const statesTagsetTemplate = - await this.tagsetTemplateSetService.addTagsetTemplate( + this.tagsetTemplateSetService.addTagsetTemplate( collaboration.tagsetTemplateSet, tagsetTemplateDataStates ); @@ -126,7 +133,7 @@ export class CollaborationService { storageAggregator ); - return await this.save(collaboration); + return collaboration; } public getCalloutGroupNames(collaboration: ICollaboration): string[] { @@ -150,16 +157,17 @@ export class CollaborationService { collaboration: ICollaboration, tagsetTemplateData: CreateTagsetTemplateInput ): Promise { - collaboration.tagsetTemplateSet = await this.getTagsetTemplatesSet( - collaboration.id - ); - - const tagsetTemplate = - await this.tagsetTemplateSetService.addTagsetTemplate( - collaboration.tagsetTemplateSet, - tagsetTemplateData + if (!collaboration.tagsetTemplateSet) { + collaboration.tagsetTemplateSet = await this.getTagsetTemplatesSet( + collaboration.id ); - await this.save(collaboration); + } + + const tagsetTemplate = this.tagsetTemplateSetService.addTagsetTemplate( + collaboration.tagsetTemplateSet, + tagsetTemplateData + ); + await this.save(collaboration); // todo remove return tagsetTemplate; } @@ -186,23 +194,35 @@ export class CollaborationService { callout.visibility = CalloutVisibility.PUBLISHED; collaboration.callouts.push(callout); } - return await this.save(collaboration); + return collaboration; } public async createCalloutInputsFromCollaboration( collaborationSource: ICollaboration ): Promise { - const calloutsData: CreateCalloutInput[] = []; - - const sourceCallouts = - await this.getCalloutsOnCollaboration(collaborationSource); + const sourceCallouts = await this.getCalloutsOnCollaboration( + collaborationSource, + { + relations: { + contributionDefaults: true, + contributionPolicy: true, + framing: { + profile: { + references: true, + location: true, + tagsets: true, + }, + whiteboard: { + profile: true, + }, + }, + }, + } + ); - for (const sourceCallout of sourceCallouts) { - const sourceCalloutInput = - await this.calloutService.createCalloutInputFromCallout(sourceCallout); - calloutsData.push(sourceCalloutInput); - } - return calloutsData; + return sourceCallouts.map( + this.calloutService.createCalloutInputFromCallout + ); } async save(collaboration: ICollaboration): Promise { @@ -609,19 +629,40 @@ export class CollaborationService { } public async getCalloutsOnCollaboration( - collaboration: ICollaboration + collaboration: ICollaboration, + opts: { + calloutIds?: string[]; + relations?: FindOptionsRelations; + } = {} ): Promise { - const loadedCollaboration = await this.getCollaborationOrFail( - collaboration.id, - { - relations: { callouts: true }, - } - ); - if (!loadedCollaboration.callouts) + const { calloutIds, relations } = opts; + const loadedCollaboration = await this.collaborationRepository.findOne({ + where: { + id: collaboration.id, + callouts: calloutIds ? { id: In(calloutIds) } : undefined, + }, + relations: { callouts: relations ?? true }, + }); + + if (!loadedCollaboration) { throw new EntityNotFoundException( - `Callouts not initialised on collaboration: ${collaboration.id}`, - LogContext.CONTEXT + 'Collaboration not found', + LogContext.COLLABORATION, + { + collaborationID: collaboration.id, + } ); + } + + if (!loadedCollaboration.callouts) { + throw new EntityNotFoundException( + 'Callouts not initialised on collaboration', + LogContext.COLLABORATION, + { + collaborationID: collaboration.id, + } + ); + } return loadedCollaboration.callouts; } diff --git a/src/domain/collaboration/innovation-flow/innovaton.flow.service.ts b/src/domain/collaboration/innovation-flow/innovaton.flow.service.ts index 19a1a65a76..9d8bcc41fe 100644 --- a/src/domain/collaboration/innovation-flow/innovaton.flow.service.ts +++ b/src/domain/collaboration/innovation-flow/innovaton.flow.service.ts @@ -83,7 +83,7 @@ export class InnovationFlowService { storageAggregator ); - await this.profileService.addVisualOnProfile( + this.profileService.addVisualOnProfile( innovationFlow.profile, VisualType.CARD ); @@ -95,7 +95,7 @@ export class InnovationFlowService { innovationFlow.states = this.innovationFlowStatesService.serializeStates(convertedStates); - return await this.innovationFlowRepository.save(innovationFlow); + return innovationFlow; } async save(innovationFlow: IInnovationFlow): Promise { diff --git a/src/domain/common/form/form.service.ts b/src/domain/common/form/form.service.ts index 9dac87cd5c..6ecb02baef 100644 --- a/src/domain/common/form/form.service.ts +++ b/src/domain/common/form/form.service.ts @@ -16,12 +16,12 @@ export class FormService { @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} - public createForm(createFormData: CreateFormInput): Promise { + public createForm(createFormData: CreateFormInput): IForm { const form: IForm = new Form(); form.description = createFormData.description; form.questions = this.serializeQuestions(createFormData.questions); - return this.save(form); + return form; } public async removeForm(form: IForm): Promise { diff --git a/src/domain/common/tagset-template-set/tagset.template.set.service.ts b/src/domain/common/tagset-template-set/tagset.template.set.service.ts index 2f14a69131..c3c51cb370 100644 --- a/src/domain/common/tagset-template-set/tagset.template.set.service.ts +++ b/src/domain/common/tagset-template-set/tagset.template.set.service.ts @@ -2,10 +2,7 @@ import { Inject, Injectable, LoggerService } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { FindOneOptions, Repository } from 'typeorm'; -import { - EntityNotFoundException, - ValidationException, -} from '@common/exceptions'; +import { EntityNotFoundException, ValidationException } from '@common/exceptions'; import { LogContext } from '@common/enums'; import { TagsetTemplateSet } from './tagset.template.set.entity'; import { TagsetTemplateService } from '../tagset-template/tagset.template.service'; @@ -22,11 +19,10 @@ export class TagsetTemplateSetService { @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} - async createTagsetTemplateSet(): Promise { - const tagsetTemplateSet: ITagsetTemplateSet = TagsetTemplateSet.create(); - tagsetTemplateSet.tagsetTemplates = []; - - return await this.save(tagsetTemplateSet); + public createTagsetTemplateSet(): ITagsetTemplateSet { + return TagsetTemplateSet.create({ + tagsetTemplates: [], + }); } async deleteTagsetTemplateSet( @@ -98,10 +94,10 @@ export class TagsetTemplateSetService { return false; } - async addTagsetTemplate( + public addTagsetTemplate( tagsetTemplateSet: ITagsetTemplateSet, tagsetTemplateData: CreateTagsetTemplateInput - ): Promise { + ): ITagsetTemplate { // Check if the group already exists, if so log a warning if ( this.hasTagsetTemplateWithName(tagsetTemplateSet, tagsetTemplateData.name) @@ -112,11 +108,9 @@ export class TagsetTemplateSetService { ); } - const tagsetTemplate = - await this.tagsetTemplateService.createTagsetTemplate(tagsetTemplateData); + const tagsetTemplate = this.tagsetTemplateService.createTagsetTemplate(tagsetTemplateData); tagsetTemplateSet.tagsetTemplates.push(tagsetTemplate); - await this.save(tagsetTemplateSet); return tagsetTemplate; } } diff --git a/src/domain/common/tagset-template/tagset.template.service.ts b/src/domain/common/tagset-template/tagset.template.service.ts index 586e3ee8ab..f0311411a1 100644 --- a/src/domain/common/tagset-template/tagset.template.service.ts +++ b/src/domain/common/tagset-template/tagset.template.service.ts @@ -5,10 +5,7 @@ import { TagsetTemplate } from './tagset.template.entity'; import { ITagsetTemplate } from './tagset.template.interface'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { LogContext } from '@common/enums'; -import { - EntityNotFoundException, - ValidationException, -} from '@common/exceptions'; +import { EntityNotFoundException, ValidationException } from '@common/exceptions'; import { CreateTagsetTemplateInput } from '@domain/common/tagset-template/dto/tagset.template.dto.create'; import { UpdateTagsetTemplateDefinitionInput } from './dto/tagset.template.dto.update'; @@ -20,17 +17,15 @@ export class TagsetTemplateService { @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} - async createTagsetTemplate( + public createTagsetTemplate( tagsetTemplateData: CreateTagsetTemplateInput - ): Promise { - const tagsetTemplate = new TagsetTemplate( + ): ITagsetTemplate { + return new TagsetTemplate( tagsetTemplateData.name, tagsetTemplateData.type, tagsetTemplateData.allowedValues, tagsetTemplateData.defaultSelectedValue ); - - return await this.tagsetTemplateRepository.save(tagsetTemplate); } async getTagsetTemplateOrFail( diff --git a/src/domain/communication/communication/communication.service.ts b/src/domain/communication/communication/communication.service.ts index 4b1443a049..274278aea3 100644 --- a/src/domain/communication/communication/communication.service.ts +++ b/src/domain/communication/communication/communication.service.ts @@ -44,7 +44,7 @@ export class CommunicationService { RoomType.UPDATES ); - return await this.communicationRepository.save(communication); + return communication; } async save(communication: ICommunication): Promise { diff --git a/src/domain/community/community-guidelines/community.guidelines.service.ts b/src/domain/community/community-guidelines/community.guidelines.service.ts index d7989e71da..2718421b1a 100644 --- a/src/domain/community/community-guidelines/community.guidelines.service.ts +++ b/src/domain/community/community-guidelines/community.guidelines.service.ts @@ -49,12 +49,12 @@ export class CommunityGuidelinesService { storageAggregator ); - await this.profileService.addVisualOnProfile( + this.profileService.addVisualOnProfile( communityGuidelines.profile, VisualType.CARD ); - return await this.communityGuidelinesRepository.save(communityGuidelines); + return communityGuidelines; } async save( diff --git a/src/domain/community/community-policy/community.policy.service.ts b/src/domain/community/community-policy/community.policy.service.ts index d65264dca5..a512252c9a 100644 --- a/src/domain/community/community-policy/community.policy.service.ts +++ b/src/domain/community/community-policy/community.policy.service.ts @@ -24,13 +24,12 @@ export class CommunityPolicyService { member: ICommunityRolePolicy, lead: ICommunityRolePolicy, admin: ICommunityRolePolicy - ): Promise { - const policy: ICommunityPolicy = new CommunityPolicy( + ): ICommunityPolicy { + return new CommunityPolicy( this.serializeRolePolicy(member), this.serializeRolePolicy(lead), this.serializeRolePolicy(admin) - ); - return this.save(policy); + ) } public async removeCommunityPolicy( @@ -123,7 +122,7 @@ export class CommunityPolicyService { public updateCommunityPolicyResourceID( communityPolicy: ICommunityPolicy, resourceID: string - ): Promise { + ): ICommunityPolicy { const memberPolicy = this.deserializeRolePolicy(communityPolicy.member); memberPolicy.credential.resourceID = resourceID; communityPolicy.member = this.serializeRolePolicy(memberPolicy); @@ -136,13 +135,13 @@ export class CommunityPolicyService { adminPolicy.credential.resourceID = resourceID; communityPolicy.admin = this.serializeRolePolicy(adminPolicy); - return this.save(communityPolicy); + return communityPolicy; } public inheritParentCredentials( communityPolicyParent: ICommunityPolicy, communityPolicy: ICommunityPolicy - ): Promise { + ): ICommunityPolicy { const memberPolicy = this.inheritParentRoleCredentials( communityPolicyParent.member, communityPolicy.member @@ -160,7 +159,7 @@ export class CommunityPolicyService { communityPolicy.lead = this.serializeRolePolicy(leadPolicy); communityPolicy.admin = this.serializeRolePolicy(adminPolicy); - return this.save(communityPolicy); + return communityPolicy; } private save(policy: ICommunityPolicy): Promise { diff --git a/src/domain/community/community/community.service.ts b/src/domain/community/community/community.service.ts index 28fb329a64..2be38b1b26 100644 --- a/src/domain/community/community/community.service.ts +++ b/src/domain/community/community/community.service.ts @@ -62,7 +62,7 @@ export class CommunityService { const community: ICommunity = new Community(); community.authorization = new AuthorizationPolicy(); const policy = communityData.policy as ICommunityPolicyDefinition; - community.policy = await this.communityPolicyService.createCommunityPolicy( + community.policy = this.communityPolicyService.createCommunityPolicy( policy.member, policy.lead, policy.admin @@ -73,7 +73,7 @@ export class CommunityService { communityData.guidelines, storageAggregator ); - community.applicationForm = await this.formService.createForm( + community.applicationForm = this.formService.createForm( communityData.applicationForm ); @@ -87,7 +87,7 @@ export class CommunityService { communityData.name, '' ); - return await this.communityRepository.save(community); + return community; } async createGroup(groupData: CreateUserGroupInput): Promise { @@ -281,23 +281,24 @@ export class CommunityService { return await this.save(community); } - async setParentCommunity( + public setParentCommunity( community?: ICommunity, parentCommunity?: ICommunity - ): Promise { - if (!community || !parentCommunity) + ): ICommunity { + if (!community || !parentCommunity) { throw new EntityNotInitializedException( 'Community not set', LogContext.COMMUNITY ); + } community.parentCommunity = parentCommunity; // Also update the communityPolicy - community.policy = - await this.communityPolicyService.inheritParentCredentials( - this.getCommunityPolicy(parentCommunity), - this.getCommunityPolicy(community) - ); - return await this.communityRepository.save(community); + community.policy = this.communityPolicyService.inheritParentCredentials( + this.getCommunityPolicy(parentCommunity), + this.getCommunityPolicy(community) + ); + + return community; } public async getDisplayName(community: ICommunity): Promise { @@ -435,7 +436,7 @@ export class CommunityService { public updateCommunityPolicyResourceID( community: ICommunity, resourceID: string - ): Promise { + ): ICommunityPolicy { const policy = this.getCommunityPolicy(community); return this.communityPolicyService.updateCommunityPolicyResourceID( policy, diff --git a/src/domain/context/actor-group/actor-group.service.ts b/src/domain/context/actor-group/actor-group.service.ts index dce3ce8519..c5b932fd9e 100644 --- a/src/domain/context/actor-group/actor-group.service.ts +++ b/src/domain/context/actor-group/actor-group.service.ts @@ -1,12 +1,7 @@ import { Inject, Injectable, LoggerService } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; -import { - ActorGroup, - IActorGroup, - CreateActorGroupInput, - DeleteActorGroupInput, -} from '@domain/context/actor-group'; +import { ActorGroup, CreateActorGroupInput, DeleteActorGroupInput, IActorGroup } from '@domain/context/actor-group'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; import { ActorService } from '@domain/context/actor/actor.service'; import { @@ -29,15 +24,14 @@ export class ActorGroupService { @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} - async createActorGroup( + public createActorGroup( actorGroupData: CreateActorGroupInput - ): Promise { - const actorGroup: IActorGroup = ActorGroup.create({ + ): IActorGroup { + return ActorGroup.create({ ...actorGroupData, + authorization: new AuthorizationPolicy(), + actors: [], }); - actorGroup.authorization = new AuthorizationPolicy(); - actorGroup.actors = []; - return await this.actorGroupRepository.save(actorGroup); } async deleteActorGroup( diff --git a/src/domain/context/context/context.service.ts b/src/domain/context/context/context.service.ts index f4826ae999..9677ff76c4 100644 --- a/src/domain/context/context/context.service.ts +++ b/src/domain/context/context/context.service.ts @@ -4,7 +4,7 @@ import { FindOneOptions, Repository } from 'typeorm'; import { EntityNotFoundException } from '@common/exceptions'; import { LogContext } from '@common/enums'; import { ReferenceService } from '@domain/common/reference/reference.service'; -import { IContext, Context, CreateContextInput } from '@domain/context/context'; +import { Context, CreateContextInput, IContext } from '@domain/context/context'; import { IEcosystemModel } from '@domain/context/ecosystem-model'; import { AuthorizationPolicy } from '@domain/common/authorization-policy'; import { EcosystemModelService } from '@domain/context/ecosystem-model/ecosystem-model.service'; @@ -21,14 +21,12 @@ export class ContextService { private contextRepository: Repository ) {} - async createContext(contextData: CreateContextInput): Promise { - const context: IContext = Context.create({ ...contextData }); - - context.ecosystemModel = - await this.ecosystemModelService.createEcosystemModel({}); - context.authorization = new AuthorizationPolicy(); - - return await this.contextRepository.save(context); + public createContext(contextData?: CreateContextInput): IContext { + return Context.create({ + ...contextData, + authorization: new AuthorizationPolicy(), + ecosystemModel: this.ecosystemModelService.createEcosystemModel({}), + }) } async getContextOrFail( diff --git a/src/domain/context/ecosystem-model/ecosystem-model.service.ts b/src/domain/context/ecosystem-model/ecosystem-model.service.ts index 513af8e2fe..01527e0499 100644 --- a/src/domain/context/ecosystem-model/ecosystem-model.service.ts +++ b/src/domain/context/ecosystem-model/ecosystem-model.service.ts @@ -32,16 +32,18 @@ export class EcosystemModelService { private ecosystemModelRepository: Repository ) {} - async createEcosystemModel( + public createEcosystemModel( ecosystemModelData: CreateEcosystemModelInput - ): Promise { + ): IEcosystemModel { const ecosystemModel: IEcosystemModel = EcosystemModel.create({ ...ecosystemModelData, + authorization: new AuthorizationPolicy(), + actorGroups: [], }); - ecosystemModel.authorization = new AuthorizationPolicy(); - await this.createRestrictedActorGroups(ecosystemModel); - ecosystemModel.actorGroups = []; - return await this.ecosystemModelRepository.save(ecosystemModel); + + this.createRestrictedActorGroups(ecosystemModel); + + return ecosystemModel; } async getEcosystemModelOrFail( @@ -90,25 +92,24 @@ export class EcosystemModelService { ); } - async createRestrictedActorGroups( + public createRestrictedActorGroups( ecosystem: IEcosystemModel - ): Promise { + ): void { if (!ecosystem.restrictedActorGroupNames) { throw new EntityNotInitializedException( 'Non-initialised EcosystemModel submitted', LogContext.SPACES ); } + ecosystem.actorGroups = []; for (const name of ecosystem.restrictedActorGroupNames) { - const actorGroup = await this.actorGroupService.createActorGroup({ + const actorGroup = this.actorGroupService.createActorGroup({ ecosystemModelID: '', name: name, description: 'Default actor group', }); - ecosystem.actorGroups?.push(actorGroup); - await this.ecosystemModelRepository.save(ecosystem); + ecosystem.actorGroups.push(actorGroup); } - return true; } async createActorGroup( diff --git a/src/domain/space/account/account.service.ts b/src/domain/space/account/account.service.ts index d627752ea0..3ca1a0cf42 100644 --- a/src/domain/space/account/account.service.ts +++ b/src/domain/space/account/account.service.ts @@ -167,12 +167,11 @@ export class AccountService { spaceData.level = SpaceLevel.SPACE; spaceData.storageAggregatorParent = account.storageAggregator; - const space = await this.spaceService.createSpace( + account.space = await this.spaceService.createSpace( spaceData, account, agentInfo ); - account.space = space; const savedAccount = await this.save(account); await this.spaceService.assignUserToRoles(account.space, agentInfo); diff --git a/src/domain/space/space.defaults/space.defaults.service.ts b/src/domain/space/space.defaults/space.defaults.service.ts index c054bec7be..ab5bcd9e1c 100644 --- a/src/domain/space/space.defaults/space.defaults.service.ts +++ b/src/domain/space/space.defaults/space.defaults.service.ts @@ -9,7 +9,9 @@ import { UUID_LENGTH } from '@common/constants/entity.field.length.constants'; import { AuthorizationPolicyService } from '@domain/common/authorization-policy/authorization.policy.service'; import { SpaceDefaults } from './space.defaults.entity'; import { InnovationFlowStatesService } from '@domain/collaboration/innovation-flow-states/innovaton.flow.state.service'; -import { InnovationFlowTemplateService } from '@domain/template/innovation-flow-template/innovation.flow.template.service'; +import { + InnovationFlowTemplateService, +} from '@domain/template/innovation-flow-template/innovation.flow.template.service'; import { ITemplatesSet } from '@domain/template/templates-set'; import { TemplatesSetService } from '@domain/template/templates-set/templates.set.service'; import { IInnovationFlowTemplate } from '@domain/template/innovation-flow-template/innovation.flow.template.interface'; @@ -33,7 +35,9 @@ import { SpaceLevel } from '@common/enums/space.level'; import { EntityNotInitializedException } from '@common/exceptions/entity.not.initialized.exception'; import { SpaceType } from '@common/enums/space.type'; import { spaceDefaultsCalloutGroupsChallenge } from './definitions/challenge/space.defaults.callout.groups.challenge'; -import { spaceDefaultsCalloutGroupsOpportunity } from './definitions/oppportunity/space.defaults.callout.groups.opportunity'; +import { + spaceDefaultsCalloutGroupsOpportunity, +} from './definitions/oppportunity/space.defaults.callout.groups.opportunity'; import { spaceDefaultsCalloutGroupsRootSpace } from './definitions/root-space/space.defaults.callout.groups.root.space'; import { spaceDefaultsCalloutGroupsKnowledge } from './definitions/knowledge/space.defaults.callout.groups.knowledge'; import { spaceDefaultsCalloutsOpportunity } from './definitions/oppportunity/space.defaults.callouts.opportunity'; @@ -44,15 +48,27 @@ import { spaceDefaultsSettingsRootSpace } from './definitions/root-space/space.d import { spaceDefaultsSettingsOpportunity } from './definitions/oppportunity/space.defaults.settings.opportunity'; import { spaceDefaultsSettingsChallenge } from './definitions/challenge/space.defaults.settings.challenge'; import { spaceDefaultsSettingsKnowledge } from './definitions/knowledge/space.defaults.settings.knowledge'; -import { spaceDefaultsInnovationFlowStatesChallenge } from './definitions/challenge/space.defaults.innovation.flow.challenge'; -import { spaceDefaultsInnovationFlowStatesOpportunity } from './definitions/oppportunity/space.defaults.innovation.flow.opportunity'; -import { spaceDefaultsInnovationFlowStatesRootSpace } from './definitions/root-space/space.defaults.innovation.flow.root.space'; -import { spaceDefaultsInnovationFlowStatesKnowledge } from './definitions/knowledge/space.defaults.innovation.flow.knowledge'; +import { + spaceDefaultsInnovationFlowStatesChallenge, +} from './definitions/challenge/space.defaults.innovation.flow.challenge'; +import { + spaceDefaultsInnovationFlowStatesOpportunity, +} from './definitions/oppportunity/space.defaults.innovation.flow.opportunity'; +import { + spaceDefaultsInnovationFlowStatesRootSpace, +} from './definitions/root-space/space.defaults.innovation.flow.root.space'; +import { + spaceDefaultsInnovationFlowStatesKnowledge, +} from './definitions/knowledge/space.defaults.innovation.flow.knowledge'; import { IInnovationFlowState } from '@domain/collaboration/innovation-flow-states/innovation.flow.state.interface'; -import { spaceDefaultsCalloutGroupsBlankSlate } from './definitions/blank-slate/space.defaults.callout.groups.blank.slate'; +import { + spaceDefaultsCalloutGroupsBlankSlate, +} from './definitions/blank-slate/space.defaults.callout.groups.blank.slate'; import { spaceDefaultsCalloutsBlankSlate } from './definitions/blank-slate/space.defaults.callouts.blank.slate'; import { spaceDefaultsSettingsBlankSlate } from './definitions/blank-slate/space.defaults.settings.blank.slate'; -import { spaceDefaultsInnovationFlowStatesBlankSlate } from './definitions/blank-slate/space.defaults.innovation.flow.blank.slate'; +import { + spaceDefaultsInnovationFlowStatesBlankSlate, +} from './definitions/blank-slate/space.defaults.innovation.flow.blank.slate'; @Injectable() export class SpaceDefaultsService { @@ -307,14 +323,13 @@ export class SpaceDefaultsService { } ); // Note: no profile currently present, so use the one from the template for now - const result: CreateInnovationFlowInput = { + return { profile: { displayName: template.profile.displayName, description: template.profile.description, }, states: this.innovationFlowStatesService.getStates(template.states), }; - return result; } // If no argument is provided, then use the default template for the space, if set @@ -358,11 +373,11 @@ export class SpaceDefaultsService { return result; } - public async getCreateCalloutInputs( + public getCreateCalloutInputs( defaultCallouts: CreateCalloutInput[], calloutsFromCollaborationTemplateInput: CreateCalloutInput[], collaborationData?: CreateCollaborationInput - ): Promise { + ): CreateCalloutInput[] { let calloutInputs: CreateCalloutInput[] = []; const addDefaultCallouts = collaborationData?.addDefaultCallouts; if (addDefaultCallouts === undefined || addDefaultCallouts) { diff --git a/src/domain/space/space/space.service.ts b/src/domain/space/space/space.service.ts index dfd5a81fb9..145e6b1e2e 100644 --- a/src/domain/space/space/space.service.ts +++ b/src/domain/space/space/space.service.ts @@ -82,7 +82,7 @@ export class SpaceService { @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} - async createSpace( + public async createSpace( spaceData: CreateSpaceInput, account: IAccount, agentInfo?: AgentInfo @@ -119,6 +119,21 @@ export class SpaceService { // default to demo space space.visibility = SpaceVisibility.ACTIVE; + const initializedSpace = await this.initialise( + space, + spaceData, + account, + agentInfo + ); + return this.save(initializedSpace); + } + + private async initialise( + space: ISpace, + spaceData: CreateSpaceInput, + account: IAccount, + agentInfo: AgentInfo | undefined + ): Promise { space.authorization = new AuthorizationPolicy(); space.account = account; space.settingsStr = this.spaceSettingsService.serializeSettings( @@ -155,10 +170,7 @@ export class SpaceService { storageAggregator ); - if (!spaceData.context) { - spaceData.context = {}; - } - space.context = await this.contextService.createContext(spaceData.context); + space.context = this.contextService.createContext(spaceData.context); const profileType = this.spaceDefaultsService.getProfileType(space.level); space.profile = await this.profileService.createProfile( @@ -172,18 +184,9 @@ export class SpaceService { }); // add the visuals - await this.profileService.addVisualOnProfile( - space.profile, - VisualType.AVATAR - ); - await this.profileService.addVisualOnProfile( - space.profile, - VisualType.BANNER - ); - await this.profileService.addVisualOnProfile( - space.profile, - VisualType.CARD - ); + this.profileService.addVisualOnProfile(space.profile, VisualType.AVATAR); + this.profileService.addVisualOnProfile(space.profile, VisualType.BANNER); + this.profileService.addVisualOnProfile(space.profile, VisualType.CARD); //// Collaboration @@ -210,12 +213,11 @@ export class SpaceService { const defaultCallouts = this.spaceDefaultsService.getDefaultCallouts( space.type ); - const calloutInputs = - await this.spaceDefaultsService.getCreateCalloutInputs( - defaultCallouts, - calloutInputsFromCollaborationTemplate, - spaceData.collaborationData - ); + const calloutInputs = this.spaceDefaultsService.getCreateCalloutInputs( + defaultCallouts, + calloutInputsFromCollaborationTemplate, + spaceData.collaborationData + ); space.collaboration = await this.collaborationService.addDefaultCallouts( space.collaboration, calloutInputs, @@ -239,12 +241,12 @@ export class SpaceService { // set immediate community parent + resourceID space.community.parentID = space.id; space.community.policy = - await this.communityService.updateCommunityPolicyResourceID( + this.communityService.updateCommunityPolicyResourceID( space.community, space.id ); - return await this.save(space); + return space; } async save(space: ISpace): Promise { @@ -776,7 +778,8 @@ export class SpaceService { agentInfo ); - subspace = await this.addSubspaceToSpace(space, subspace); + subspace = this.addSubspaceToSpace(space, subspace); + subspace = await this.save(subspace); // Before assigning roles in the subspace check that the user is a member if (agentInfo) { @@ -793,24 +796,25 @@ export class SpaceService { return subspace; } - async addSubspaceToSpace(space: ISpace, subspace: ISpace): Promise { - if (!space.community) + public addSubspaceToSpace(space: ISpace, subspace: ISpace): ISpace { + if (!space.community) { throw new ValidationException( `Unable to add Subspace to space, missing relations: ${space.id}`, LogContext.SPACES ); + } // Set the parent space directly, avoiding saving the whole parent subspace.parentSpace = space; subspace.levelZeroSpaceID = space.levelZeroSpaceID; // Finally set the community relationship - await this.setCommunityHierarchyForSubspace( + subspace.community = this.setCommunityHierarchyForSubspace( space.community, subspace.community ); - return await this.save(subspace); + return subspace; } async getSubspace(subspaceID: string, space: ISpace): Promise { @@ -1004,10 +1008,10 @@ export class SpaceService { return this.spaceSettingsService.getSettings(space.settingsStr); } - public async setCommunityHierarchyForSubspace( + public setCommunityHierarchyForSubspace( parentCommunity: ICommunity, childCommunity: ICommunity | undefined - ) { + ): ICommunity { if (!childCommunity) { throw new RelationshipNotFoundException( `Unable to set subspace community relationship, child community not provied: ${parentCommunity.id}`, @@ -1015,7 +1019,7 @@ export class SpaceService { ); } // Finally set the community relationship - await this.communityService.setParentCommunity( + return this.communityService.setParentCommunity( childCommunity, parentCommunity ); diff --git a/src/domain/storage/document/document.service.ts b/src/domain/storage/document/document.service.ts index ee73a74f60..dd714f2dbd 100644 --- a/src/domain/storage/document/document.service.ts +++ b/src/domain/storage/document/document.service.ts @@ -202,7 +202,10 @@ export class DocumentService { } private getDocumentsBaseUrlPath(): string { - const { endpoint_cluster, path_api_private_rest } = this.configService.get('hosting', { infer: true }); + const { endpoint_cluster, path_api_private_rest } = this.configService.get( + 'hosting', + { infer: true } + ); return `${endpoint_cluster}${path_api_private_rest}/storage/document`; } diff --git a/src/domain/template/innovation-flow-template/innovation.flow.template.service.ts b/src/domain/template/innovation-flow-template/innovation.flow.template.service.ts index 5ffa065790..28d90422a1 100644 --- a/src/domain/template/innovation-flow-template/innovation.flow.template.service.ts +++ b/src/domain/template/innovation-flow-template/innovation.flow.template.service.ts @@ -60,11 +60,13 @@ export class InnovationFlowTemplateService { ...options, }); - if (!innovationFlowTemplate) + if (!innovationFlowTemplate) { throw new EntityNotFoundException( `Not able to locate InnovationFlowTemplate with the specified ID: ${innovationFlowTemplateID}`, LogContext.COMMUNICATION ); + } + return innovationFlowTemplate; } diff --git a/src/domain/timeline/calendar/calendar.service.ts b/src/domain/timeline/calendar/calendar.service.ts index 4375116b61..1a1b47a668 100644 --- a/src/domain/timeline/calendar/calendar.service.ts +++ b/src/domain/timeline/calendar/calendar.service.ts @@ -40,12 +40,12 @@ export class CalendarService { @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} - public async createCalendar(): Promise { + public createCalendar(): ICalendar { const calendar: ICalendar = new Calendar(); calendar.authorization = new AuthorizationPolicy(); calendar.events = []; - return await this.calendarRepository.save(calendar); + return calendar; } async deleteCalendar(calendarID: string): Promise { diff --git a/src/domain/timeline/timeline/timeline.service.ts b/src/domain/timeline/timeline/timeline.service.ts index 808244df38..79c62562a9 100644 --- a/src/domain/timeline/timeline/timeline.service.ts +++ b/src/domain/timeline/timeline/timeline.service.ts @@ -21,12 +21,12 @@ export class TimelineService { @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} - public async createTimeline(): Promise { + public createTimeline(): ITimeline { const timeline: ITimeline = new Timeline(); timeline.authorization = new AuthorizationPolicy(); - timeline.calendar = await this.calendarService.createCalendar(); + timeline.calendar = this.calendarService.createCalendar(); - return await this.timelineRepository.save(timeline); + return timeline; } async deleteTimeline(timelineID: string): Promise { diff --git a/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts b/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts index e0c609b2c5..f8c5ba1ead 100644 --- a/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts +++ b/src/services/adapters/ssi-sovrhd/ssi.sovrhd.adapter.ts @@ -31,7 +31,9 @@ export class SsiSovrhdAdapter { private configService: ConfigService, private httpService: HttpService ) { - const sovrhdConfig = this.configService.get('ssi.issuers.sovrhd', { infer: true }); + const sovrhdConfig = this.configService.get('ssi.issuers.sovrhd', { + infer: true, + }); this.sovrhdApiEndpoint = sovrhdConfig.endpoint; this.credentialTypesMap = new Map(); diff --git a/src/services/adapters/storage/local-storage/local.storage.adapter.ts b/src/services/adapters/storage/local-storage/local.storage.adapter.ts index 647acdc67d..299650b344 100644 --- a/src/services/adapters/storage/local-storage/local.storage.adapter.ts +++ b/src/services/adapters/storage/local-storage/local.storage.adapter.ts @@ -23,7 +23,10 @@ export class LocalStorageAdapter implements StorageService { private readonly storagePath: string; constructor(private configService: ConfigService) { - const pathFromConfig = this.configService.get('storage.local_storage.path', { infer: true }); + const pathFromConfig = this.configService.get( + 'storage.local_storage.path', + { infer: true } + ); this.storagePath = pathResolve(pathFromConfig); this.ensureStoragePathExists(); } diff --git a/src/services/ai-server/ai-server/ai.server.service.ts b/src/services/ai-server/ai-server/ai.server.service.ts index 92a058b439..5c61ec2a83 100644 --- a/src/services/ai-server/ai-server/ai.server.service.ts +++ b/src/services/ai-server/ai-server/ai.server.service.ts @@ -153,7 +153,9 @@ export class AiServerService { } private async isContextLoaded(contextID: string): Promise { - const { host, port } = this.config.get('platform.vector_db', { infer: true }); + const { host, port } = this.config.get('platform.vector_db', { + infer: true, + }); const chroma = new ChromaClient({ path: `http://${host}:${port}` }); const name = this.getContextCollectionID(contextID); @@ -275,9 +277,8 @@ export class AiServerService { engine: aiPersonaService.engine, userID: '', }; - const result = await this.aiPersonaEngineAdapter.sendIngest( - ingestAdapterInput - ); + const result = + await this.aiPersonaEngineAdapter.sendIngest(ingestAdapterInput); return result; } } diff --git a/src/services/api/chat-guidance/chat.guidance.service.ts b/src/services/api/chat-guidance/chat.guidance.service.ts index 4d02977556..4d9126b71e 100644 --- a/src/services/api/chat-guidance/chat.guidance.service.ts +++ b/src/services/api/chat-guidance/chat.guidance.service.ts @@ -40,6 +40,8 @@ export class ChatGuidanceService { } public isGuidanceEngineEnabled(): boolean { - return this.configService.get('platform.guidance_engine.enabled', { infer: true }) + return this.configService.get('platform.guidance_engine.enabled', { + infer: true, + }); } } diff --git a/src/services/api/search/v1/search.resolver.queries.ts b/src/services/api/search/v1/search.resolver.queries.ts index 88155db31b..b4f5d82223 100644 --- a/src/services/api/search/v1/search.resolver.queries.ts +++ b/src/services/api/search/v1/search.resolver.queries.ts @@ -17,7 +17,9 @@ export class SearchResolverQueries { private searchService: SearchService, private search2Service: Search2Service ) { - this.useNewSearch = this.configService.get('search.use_new', { infer: true }); + this.useNewSearch = this.configService.get('search.use_new', { + infer: true, + }); } @UseGuards(GraphqlGuard) diff --git a/src/services/api/search/v2/extract/search.extract.service.ts b/src/services/api/search/v2/extract/search.extract.service.ts index 35d8dd0d5c..2d2a3b095c 100644 --- a/src/services/api/search/v2/extract/search.extract.service.ts +++ b/src/services/api/search/v2/extract/search.extract.service.ts @@ -5,10 +5,7 @@ import { ConfigService } from '@nestjs/config'; import { Client as ElasticClient } from '@elastic/elasticsearch'; import { ELASTICSEARCH_CLIENT_PROVIDER } from '@constants/index'; import { IBaseAlkemio } from '@domain/common/entity/base-entity'; -import { - AlkemioErrorStatus, - LogContext, -} from '@common/enums'; +import { AlkemioErrorStatus, LogContext } from '@common/enums'; import { BaseException } from '@common/exceptions/base.exception'; import { ISearchResult, SearchInput } from '../../dto'; import { validateSearchTerms, validateSearchParameters } from '../../util'; diff --git a/src/services/api/search/v2/ingest/get.index.pattern.ts b/src/services/api/search/v2/ingest/get.index.pattern.ts index ec712cab33..f873f5fe40 100644 --- a/src/services/api/search/v2/ingest/get.index.pattern.ts +++ b/src/services/api/search/v2/ingest/get.index.pattern.ts @@ -6,6 +6,8 @@ const DEFAULT_INDEX_PATTERN = 'alkemio-data-'; export const getIndexPattern = ( configService: ConfigService ) => { - return configService.get('search.index_pattern', { infer: true }) ?? - DEFAULT_INDEX_PATTERN; + return ( + configService.get('search.index_pattern', { infer: true }) ?? + DEFAULT_INDEX_PATTERN + ); }; diff --git a/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts b/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts index b82129b507..1b6dd6ef73 100644 --- a/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts +++ b/src/services/external/elasticsearch/contribution-reporter/contribution.reporter.service.ts @@ -29,9 +29,13 @@ export class ContributionReporterService { @Inject(ELASTICSEARCH_CLIENT_PROVIDER) private readonly client: ElasticClient | undefined ) { - const elasticsearch = this.configService.get('integrations.elasticsearch', { infer: true }); + const elasticsearch = this.configService.get('integrations.elasticsearch', { + infer: true, + }); - this.environment = this.configService.get('hosting.environment', { infer: true }); + this.environment = this.configService.get('hosting.environment', { + infer: true, + }); this.activityIndexName = elasticsearch?.indices?.contribution; } diff --git a/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts b/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts index 17154118e7..47959bab24 100644 --- a/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts +++ b/src/services/external/elasticsearch/elasticsearch-client/elasticsearch.client.factory.ts @@ -8,7 +8,9 @@ export const elasticSearchClientFactory = async ( logger: LoggerService, configService: ConfigService ): Promise => { - const elasticsearch = configService.get('integrations.elasticsearch', { infer: true }); + const elasticsearch = configService.get('integrations.elasticsearch', { + infer: true, + }); const { host, retries, timeout, api_key, tls } = elasticsearch; const rejectUnauthorized = tls.rejectUnauthorized ?? false; diff --git a/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts b/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts index 11e579aefd..ade05d88e0 100644 --- a/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts +++ b/src/services/external/elasticsearch/guidance-reporter/guidance.reporter.service.ts @@ -34,9 +34,13 @@ export class GuidanceReporterService { LogContext.CHAT_GUIDANCE_REPORTER ); } - const elasticsearch = this.configService.get('integrations.elasticsearch', { infer: true }); + const elasticsearch = this.configService.get('integrations.elasticsearch', { + infer: true, + }); - this.environment = this.configService.get('hosting.environment', { infer: true }); + this.environment = this.configService.get('hosting.environment', { + infer: true, + }); this.indexName = elasticsearch?.indices?.guidance_usage; } diff --git a/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts b/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts index b6d7b90ab8..1096921c05 100644 --- a/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts +++ b/src/services/external/elasticsearch/name-reporter/name.reporter.service.ts @@ -21,9 +21,13 @@ export class NameReporterService { @Inject(ELASTICSEARCH_CLIENT_PROVIDER) private readonly client: ElasticClient | undefined ) { - const elasticsearch = this.configService.get('integrations.elasticsearch', { infer: true }); + const elasticsearch = this.configService.get('integrations.elasticsearch', { + infer: true, + }); - this.environment = this.configService.get('hosting.environment', { infer: true }); + this.environment = this.configService.get('hosting.environment', { + infer: true, + }); const { indices, policies } = elasticsearch; this.indexName = indices?.namings; diff --git a/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts b/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts index 2d512cf07d..99813b037e 100644 --- a/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts +++ b/src/services/external/excalidraw-backend/adapters/redis/excalidraw.redis.server.factory.provider.ts @@ -3,10 +3,7 @@ import { createAdapter } from '@socket.io/redis-adapter'; import { FactoryProvider, LoggerService } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; -import { - AlkemioErrorStatus, - LogContext, -} from '@common/enums'; +import { AlkemioErrorStatus, LogContext } from '@common/enums'; import { BaseException } from '@common/exceptions/base.exception'; import { APP_ID, EXCALIDRAW_SERVER } from '@constants/index'; import { AuthenticationService } from '@core/authentication/authentication.service'; diff --git a/src/services/external/excalidraw-backend/excalidraw.server.ts b/src/services/external/excalidraw-backend/excalidraw.server.ts index 3bbc79eb06..48a9b4fbcd 100644 --- a/src/services/external/excalidraw-backend/excalidraw.server.ts +++ b/src/services/external/excalidraw-backend/excalidraw.server.ts @@ -128,7 +128,10 @@ export class ExcalidrawServer { } private async init() { - const kratosPublicBaseUrl = this.configService.get('identity.authentication.providers.ory.kratos_public_base_url_server', { infer: true }); + const kratosPublicBaseUrl = this.configService.get( + 'identity.authentication.providers.ory.kratos_public_base_url_server', + { infer: true } + ); const kratosClient = new FrontendApi( new Configuration({ diff --git a/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts b/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts index c89b2365ea..97430e0396 100644 --- a/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts +++ b/src/services/external/excalidraw-backend/utils/get.excalidraw.base.server.ts @@ -3,10 +3,7 @@ import { Namespace, Server as SocketIO } from 'socket.io'; import { Adapter } from 'socket.io-adapter'; import { ConfigService } from '@nestjs/config'; import { LoggerService } from '@nestjs/common'; -import { - AlkemioErrorStatus, - LogContext, -} from '@common/enums'; +import { AlkemioErrorStatus, LogContext } from '@common/enums'; import { BaseException } from '@common/exceptions/base.exception'; import { SocketIoServer } from '../types/socket.io.server'; import { AlkemioConfig } from '@src/types'; diff --git a/src/services/external/geo-location/geo.location.service.spec.ts b/src/services/external/geo-location/geo.location.service.spec.ts index a52a699536..abf8f9eb47 100644 --- a/src/services/external/geo-location/geo.location.service.spec.ts +++ b/src/services/external/geo-location/geo.location.service.spec.ts @@ -162,16 +162,16 @@ describe('GeoLocationService', () => { // incrementCacheMetadata expect(spySet).toHaveBeenNthCalledWith( 1, - "geo-service-call-limit", - { start: 1, calls: 1 }, - { ttl: 1 } + 'geo-service-call-limit', + { start: 1, calls: 1 }, + { ttl: 1 } ); // set data in cache expect(spySet).toHaveBeenNthCalledWith( 2, - 'ip', - { latitude: 1, longitude: 2 }, - { ttl: 1 }, + 'ip', + { latitude: 1, longitude: 2 }, + { ttl: 1 } ); expect(result).toStrictEqual({ latitude: 1, diff --git a/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts b/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts index 3c015a6deb..238b8161ba 100644 --- a/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts +++ b/src/services/external/trust-registry/trust.registry.adapter/trust.registry.adapter.ts @@ -135,7 +135,10 @@ export class TrustRegistryAdapter { } private generatePublicRestApiUrl() { - const { endpoint_cluster, path_api_public_rest } = this.configService.get('hosting', { infer: true }); + const { endpoint_cluster, path_api_public_rest } = this.configService.get( + 'hosting', + { infer: true } + ); return `${endpoint_cluster}${path_api_public_rest}`; } } diff --git a/src/services/infrastructure/event-bus/event.bus.module.ts b/src/services/infrastructure/event-bus/event.bus.module.ts index 84321c14e8..e649172e24 100644 --- a/src/services/infrastructure/event-bus/event.bus.module.ts +++ b/src/services/infrastructure/event-bus/event.bus.module.ts @@ -14,7 +14,10 @@ import { AlkemioConfig } from '@src/types'; imports: [ConfigModule], inject: [ConfigService], useFactory: (configService: ConfigService) => { - const rbmqConfig = configService.get('microservices.rabbitmq.connection', { infer: true }); + const rbmqConfig = configService.get( + 'microservices.rabbitmq.connection', + { infer: true } + ); return { uri: `amqp://${rbmqConfig.user}:${rbmqConfig.password}@${rbmqConfig.host}:${rbmqConfig.port}`, diff --git a/src/services/infrastructure/url-generator/url.generator.service.ts b/src/services/infrastructure/url-generator/url.generator.service.ts index f3e9935173..a515a00308 100644 --- a/src/services/infrastructure/url-generator/url.generator.service.ts +++ b/src/services/infrastructure/url-generator/url.generator.service.ts @@ -57,7 +57,9 @@ export class UrlGeneratorService { private readonly logger: LoggerService, @Inject(CACHE_MANAGER) private readonly cacheManager: Cache ) { - this.endpoint_cluster = this.configService.get('hosting.endpoint_cluster', { infer: true }); + this.endpoint_cluster = this.configService.get('hosting.endpoint_cluster', { + infer: true, + }); } private getUrlIdCacheKey(entityId: string): string { diff --git a/src/services/whiteboard-integration/whiteboard.integration.service.ts b/src/services/whiteboard-integration/whiteboard.integration.service.ts index e013a626dd..474bd2aa22 100644 --- a/src/services/whiteboard-integration/whiteboard.integration.service.ts +++ b/src/services/whiteboard-integration/whiteboard.integration.service.ts @@ -6,10 +6,7 @@ import { AgentInfo } from '@core/authentication.agent.info/agent.info'; import { WhiteboardService } from '@domain/common/whiteboard'; import { UserService } from '@domain/community/user/user.service'; import { IVerifiedCredential } from '@domain/agent/verified-credential/verified.credential.interface'; -import { - AuthorizationPrivilege, - LogContext, -} from '@common/enums'; +import { AuthorizationPrivilege, LogContext } from '@common/enums'; import { EntityNotInitializedException } from '@common/exceptions'; import { AuthenticationService } from '@core/authentication/authentication.service'; import { CommunityResolverService } from '@services/infrastructure/entity-resolver/community.resolver.service'; @@ -40,7 +37,10 @@ export class WhiteboardIntegrationService { private readonly activityAdapter: ActivityAdapter, private readonly configService: ConfigService ) { - this.maxCollaboratorsInRoom = this.configService.get('collaboration.whiteboards.max_collaborators_in_room', { infer: true }); + this.maxCollaboratorsInRoom = this.configService.get( + 'collaboration.whiteboards.max_collaborators_in_room', + { infer: true } + ); } public async accessGranted(data: AccessGrantedInputData): Promise { From ff38b885f85f5cf521dba4f72268e2d8ff44dd1d Mon Sep 17 00:00:00 2001 From: Valentin Yanakiev Date: Thu, 8 Aug 2024 14:51:22 +0300 Subject: [PATCH 24/27] Select space visibility for elastic ingestion --- src/services/api/search/v2/ingest/search.ingest.service.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/services/api/search/v2/ingest/search.ingest.service.ts b/src/services/api/search/v2/ingest/search.ingest.service.ts index 03dff2984f..9e9d8fcacb 100644 --- a/src/services/api/search/v2/ingest/search.ingest.service.ts +++ b/src/services/api/search/v2/ingest/search.ingest.service.ts @@ -52,6 +52,7 @@ const journeyFindOptions: FindManyOptions = { select: { id: true, level: true, + visibility: true, context: { vision: true, impact: true, From 8dbfd320319a5ae08f697804abe00cba21b8fc95 Mon Sep 17 00:00:00 2001 From: Valentin Yanakiev Date: Thu, 8 Aug 2024 16:04:11 +0300 Subject: [PATCH 25/27] fixes accounts with no spaces --- ...23121607785-deleteAccountsWithoutSpaces.ts | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/migrations/1723121607785-deleteAccountsWithoutSpaces.ts diff --git a/src/migrations/1723121607785-deleteAccountsWithoutSpaces.ts b/src/migrations/1723121607785-deleteAccountsWithoutSpaces.ts new file mode 100644 index 0000000000..0dd7d1eed3 --- /dev/null +++ b/src/migrations/1723121607785-deleteAccountsWithoutSpaces.ts @@ -0,0 +1,33 @@ +import { MigrationInterface, QueryRunner } from 'typeorm'; + +export class DeleteAccountsWithoutSpaces1723121607785 + implements MigrationInterface +{ + public async up(queryRunner: QueryRunner): Promise { + const credentialsToDelete: { + id: string; + }[] = await queryRunner.query( + `SELECT credential.id FROM alkemio.credential + JOIN agent on credential.agentId = agent.id + JOIN account on account.agentId = agent.id + WHERE account.spaceId IS NULL;` + ); + + if (credentialsToDelete.length === 0) { + console.log('No credentials to delete'); + return; + } + await queryRunner.query( + `DELETE FROM credential WHERE id IN (${credentialsToDelete + .map(c => `'${c.id}'`) + .join(',')});` + ); + await queryRunner.query(`DELETE FROM account WHERE spaceId IS NULL;`); + } + + public async down(_queryRunner: QueryRunner): Promise { + console.log( + 'No down migration for deleteAccountsWithoutSpaces1723121607785' + ); + } +} From c5baad4c52a2af456c6bb0b3537d00a300c01c68 Mon Sep 17 00:00:00 2001 From: Valentin Yanakiev Date: Thu, 8 Aug 2024 18:06:20 +0300 Subject: [PATCH 26/27] fix assignment of flow-state template to tagset on subspace creation (#4382) --- src/domain/space/space/space.service.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/domain/space/space/space.service.ts b/src/domain/space/space/space.service.ts index 145e6b1e2e..cfb7c0a768 100644 --- a/src/domain/space/space/space.service.ts +++ b/src/domain/space/space/space.service.ts @@ -231,6 +231,17 @@ export class SpaceService { parentDisplayID: `${space.nameID}`, }); + const flowStateTemplate = + space.collaboration.tagsetTemplateSet?.tagsetTemplates.find( + t => t.name === TagsetReservedName.FLOW_STATE + ); + if (space.collaboration.innovationFlow?.profile.tagsets) { + for (const tagset of space.collaboration.innovationFlow?.profile + ?.tagsets) { + tagset.tagsetTemplate = flowStateTemplate; + } + } + await this.save(space); if (spaceData.level === SpaceLevel.SPACE) { From ba429880e8502ca7449384f283fa988c61b372e4 Mon Sep 17 00:00:00 2001 From: Valentin Yanakiev Date: Fri, 9 Aug 2024 10:50:55 +0300 Subject: [PATCH 27/27] Major version bump --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e238658aa8..520e0a08e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "alkemio-server", - "version": "0.86.1", + "version": "0.87.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "alkemio-server", - "version": "0.86.1", + "version": "0.87.0", "license": "EUPL-1.2", "dependencies": { "@alkemio/matrix-adapter-lib": "^0.4.1", diff --git a/package.json b/package.json index a1b1a2ac9f..bf9bf241b0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "alkemio-server", - "version": "0.86.1", + "version": "0.87.0", "description": "Alkemio server, responsible for managing the shared Alkemio platform", "author": "Alkemio Foundation", "private": false,