From 7371877e851ff7bfc17732fea631d0a386efa0b1 Mon Sep 17 00:00:00 2001 From: Bobby Kolev Date: Mon, 4 Nov 2024 16:43:58 +0200 Subject: [PATCH] Subspacetemplates fixes 2 (#4667) * 0.95.0 * Subspaces templates Fixes (#4660) * 0.95.1 * - Address Valentin's comments (logging + rename of function - Fix Template Post callouts generating comments when they shouldn't - Fix 7131 - Preserve callout state * Ensure correct group and state when not adding new callouts * Collaboration templates shouldn't have a timeline --------- Co-authored-by: Carlos Cano --- package-lock.json | 4 +- package.json | 2 +- .../collaboration.service.authorization.ts | 12 +-- .../collaboration/collaboration.service.ts | 12 +-- .../space.defaults/space.defaults.service.ts | 13 ++- .../template.applier.service.ts | 87 ++++++++++++------- 6 files changed, 79 insertions(+), 51 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3dc372df56..f6cfb36727 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "alkemio-server", - "version": "0.94.0", + "version": "0.95.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "alkemio-server", - "version": "0.94.0", + "version": "0.95.1", "license": "EUPL-1.2", "dependencies": { "@alkemio/matrix-adapter-lib": "^0.4.1", diff --git a/package.json b/package.json index 4035692261..86e0c4df25 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "alkemio-server", - "version": "0.94.0", + "version": "0.95.1", "description": "Alkemio server, responsible for managing the shared Alkemio platform", "author": "Alkemio Foundation", "private": false, diff --git a/src/domain/collaboration/collaboration/collaboration.service.authorization.ts b/src/domain/collaboration/collaboration/collaboration.service.authorization.ts index 01ad0aae89..11808579a2 100644 --- a/src/domain/collaboration/collaboration/collaboration.service.authorization.ts +++ b/src/domain/collaboration/collaboration/collaboration.service.authorization.ts @@ -62,11 +62,7 @@ export class CollaborationAuthorizationService { }, } ); - if ( - !collaboration.callouts || - !collaboration.innovationFlow || - !collaboration.timeline - ) { + if (!collaboration.callouts || !collaboration.innovationFlow) { throw new RelationshipNotFoundException( `Unable to load child entities for collaboration authorization: ${collaboration.id}`, LogContext.SPACES @@ -121,8 +117,7 @@ export class CollaborationAuthorizationService { if ( !collaboration.callouts || !collaboration.innovationFlow || - !collaboration.innovationFlow.profile || - !collaboration.timeline + !collaboration.innovationFlow.profile ) { throw new RelationshipNotFoundException( `Unable to load child entities for collaboration authorization children: ${collaboration.id}`, @@ -148,7 +143,8 @@ export class CollaborationAuthorizationService { collaboration.authorization ); - if (roleSet && spaceSettings) { + // Collaboration templates don't have timeline so this won't be executed for them + if (roleSet && spaceSettings && collaboration.timeline) { const extendedAuthorizationContributors = await this.appendCredentialRulesForContributors( clonedAuthorization, diff --git a/src/domain/collaboration/collaboration/collaboration.service.ts b/src/domain/collaboration/collaboration/collaboration.service.ts index d19f67b470..15dcd0fb4c 100644 --- a/src/domain/collaboration/collaboration/collaboration.service.ts +++ b/src/domain/collaboration/collaboration/collaboration.service.ts @@ -95,12 +95,15 @@ export class CollaborationService { AuthorizationPolicyType.COLLABORATION ); collaboration.callouts = []; - collaboration.timeline = this.timelineService.createTimeline(); collaboration.groupsStr = this.calloutGroupsService.serializeGroups( collaborationData.calloutGroups ); collaboration.isTemplate = collaborationData.isTemplate || false; + if (!collaboration.isTemplate) { + collaboration.timeline = this.timelineService.createTimeline(); + } + collaboration.tagsetTemplateSet = this.tagsetTemplateSetService.createTagsetTemplateSet(); @@ -153,7 +156,7 @@ export class CollaborationService { storageAggregator ); - this.moveCalloutsToCorrectGroupAndState( + this.moveCalloutsToDefaultGroupAndState( groupTagsetTemplateInput.allowedValues, statesTagsetTemplate.allowedValues, collaboration.callouts @@ -224,6 +227,7 @@ export class CollaborationService { calloutNameIds.push(calloutDefault.nameID); } if ( + calloutDefault.isTemplate === false && calloutDefault.type === CalloutType.POST && calloutDefault.contributionPolicy?.state === CalloutState.OPEN ) { @@ -235,8 +239,6 @@ export class CollaborationService { storageAggregator, userID ); - // default callouts are already published - callout.visibility = CalloutVisibility.PUBLISHED; callouts.push(callout); } return callouts; @@ -788,7 +790,7 @@ export class CollaborationService { * Move callouts that are not in valid groups or flowStates to the default group & first flowState * @param callouts */ - public moveCalloutsToCorrectGroupAndState( + public moveCalloutsToDefaultGroupAndState( validGroupNames: string[], validFlowStateNames: string[], callouts: { diff --git a/src/domain/space/space.defaults/space.defaults.service.ts b/src/domain/space/space.defaults/space.defaults.service.ts index 7003e0fa93..c10d7d7b27 100644 --- a/src/domain/space/space.defaults/space.defaults.service.ts +++ b/src/domain/space/space.defaults/space.defaults.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common'; +import { Inject, Injectable, LoggerService } from '@nestjs/common'; import { LogContext } from '@common/enums/logging.context'; import { ISpaceSettings } from '../space.settings/space.settings.interface'; import { subspaceCommunityRoles } from './definitions/subspace.community.roles'; @@ -26,6 +26,7 @@ import { TemplateDefaultType } from '@common/enums/template.default.type'; import { ValidationException } from '@common/exceptions'; import { CollaborationService } from '@domain/collaboration/collaboration/collaboration.service'; import { ITemplatesManager } from '@domain/template/templates-manager'; +import { WINSTON_MODULE_NEST_PROVIDER } from 'nest-winston'; @Injectable() export class SpaceDefaultsService { @@ -34,7 +35,8 @@ export class SpaceDefaultsService { private inputCreatorService: InputCreatorService, private platformService: PlatformService, private collaborationService: CollaborationService, - private templatesManagerService: TemplatesManagerService + private templatesManagerService: TemplatesManagerService, + @Inject(WINSTON_MODULE_NEST_PROVIDER) private readonly logger: LoggerService ) {} public async createCollaborationInput( @@ -61,6 +63,11 @@ export class SpaceDefaultsService { } } catch (e) { // Space does not have a subspace default template, just use the platform default + this.logger.warn( + `Space does not have a subspace default template, using platform default parentSpaceTemplatesManager.id: ${parentSpaceTemplatesManager?.id}`, + undefined, + LogContext.TEMPLATES + ); } } // Get the platform default template if no parent template @@ -171,7 +178,7 @@ export class SpaceDefaultsService { state => state.displayName ); - this.collaborationService.moveCalloutsToCorrectGroupAndState( + this.collaborationService.moveCalloutsToDefaultGroupAndState( validGroupNames ?? [], validFlowStateNames ?? [], collaborationData.calloutsData ?? [] diff --git a/src/domain/template/template-applier/template.applier.service.ts b/src/domain/template/template-applier/template.applier.service.ts index 4030300103..2aa9294522 100644 --- a/src/domain/template/template-applier/template.applier.service.ts +++ b/src/domain/template/template-applier/template.applier.service.ts @@ -13,6 +13,7 @@ import { AuthorizationPolicyService } from '@domain/common/authorization-policy/ import { IAuthorizationPolicy } from '@domain/common/authorization-policy'; import { NamingService } from '@services/infrastructure/naming/naming.service'; import { TagsetReservedName } from '@common/enums/tagset.reserved.name'; +import { ICallout } from '@domain/collaboration/callout'; @Injectable() export class TemplateApplierService { @@ -76,46 +77,68 @@ export class TemplateApplierService { userID ); targetCollaboration.callouts?.push(...newCallouts); - - const validGroupNames = - targetCollaboration.tagsetTemplateSet?.tagsetTemplates.find( - tagset => tagset.name === TagsetReservedName.CALLOUT_GROUP - )?.allowedValues; - const validFlowStates = this.innovationFlowService - .getStates(targetCollaboration.innovationFlow) - ?.map(state => state.displayName); - - this.collaborationService.moveCalloutsToCorrectGroupAndState( - validGroupNames ?? [], - validFlowStates ?? [], - targetCollaboration.callouts - ); - - const authorizations: IAuthorizationPolicy[] = []; - - const { roleSet: communityPolicy, spaceSettings } = - await this.namingService.getRoleSetAndSettingsForCollaboration( - targetCollaboration.id - ); + this.ensureCalloutsInValidGroupsAndStates(targetCollaboration); // Need to save before applying authorization policy to get the callout ids const result = await this.collaborationService.save(targetCollaboration); - for (const callout of newCallouts) { - const calloutAuthorizations = - await this.calloutAuthorizationService.applyAuthorizationPolicy( - callout.id, - targetCollaboration.authorization, - communityPolicy, - spaceSettings - ); - authorizations.push(...calloutAuthorizations); - } - await this.authorizationPolicyService.saveAll(authorizations); + await this.applyAuthorizationPolicyToNewCallouts( + targetCollaboration, + newCallouts + ); return result; } else { + this.ensureCalloutsInValidGroupsAndStates(targetCollaboration); return await this.collaborationService.save(targetCollaboration); } } + private ensureCalloutsInValidGroupsAndStates( + targetCollaboration: ICollaboration + ) { + // We don't have callouts or we don't have innovationFlow, can't do anything + if (!targetCollaboration.innovationFlow || !targetCollaboration.callouts) { + throw new RelationshipNotFoundException( + `Unable to load Callouts or InnovationFlow ${targetCollaboration.id} `, + LogContext.TEMPLATES + ); + } + + const validGroupNames = + targetCollaboration.tagsetTemplateSet?.tagsetTemplates.find( + tagset => tagset.name === TagsetReservedName.CALLOUT_GROUP + )?.allowedValues; + const validFlowStates = this.innovationFlowService + .getStates(targetCollaboration.innovationFlow) + ?.map(state => state.displayName); + + this.collaborationService.moveCalloutsToDefaultGroupAndState( + validGroupNames ?? [], + validFlowStates ?? [], + targetCollaboration.callouts + ); + } + private async applyAuthorizationPolicyToNewCallouts( + targetCollaboration: ICollaboration, + newCallouts: ICallout[] + ): Promise { + const authorizations: IAuthorizationPolicy[] = []; + + const { roleSet: communityPolicy, spaceSettings } = + await this.namingService.getRoleSetAndSettingsForCollaboration( + targetCollaboration.id + ); + + for (const callout of newCallouts) { + const calloutAuthorizations = + await this.calloutAuthorizationService.applyAuthorizationPolicy( + callout.id, + targetCollaboration.authorization, + communityPolicy, + spaceSettings + ); + authorizations.push(...calloutAuthorizations); + } + return await this.authorizationPolicyService.saveAll(authorizations); + } }