Skip to content

Commit

Permalink
Merge pull request #4187 from alkem-io/develop
Browse files Browse the repository at this point in the history
Release: Fixes
  • Loading branch information
valentinyanakiev authored Jul 1, 2024
2 parents 40bf904 + 9ede23a commit 2ea98a7
Show file tree
Hide file tree
Showing 17 changed files with 258 additions and 179 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "alkemio-server",
"version": "0.82.5",
"version": "0.82.6",
"description": "Alkemio server, responsible for managing the shared Alkemio platform",
"author": "Alkemio Foundation",
"private": false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ export const CREDENTIAL_RULE_COMMUNITY_USER_INVITATION =
'credentialRule-communityUserInvitation';
export const CREDENTIAL_RULE_COMMUNITY_SELF_REMOVAL =
'credentialRule-communitySelfRemoval';
export const CREDENTIAL_RULE_COMMUNITY_VIRTUAL_CONTRIBUTOR_REMOVAL =
'credentialRule-communityVirtualContributorRemoval';
export const CREDENTIAL_RULE_COMMUNITY_ADD_MEMBER =
'credentialRule-communityAddMember';
export const CREDENTIAL_RULE_ORGANIZATION_VERIFICATION_ADMIN =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
export const CREDENTIAL_RULE_TYPES_ACCOUNT_AUTHORIZATION_RESET =
'credentialRuleTypes-accountAuthorizationReset';
export const CREDENTIAL_RULE_TYPES_ACCOUNT_DELETE =
'credentialRuleTypes-accountDelete';
export const CREDENTIAL_RULE_TYPES_SPACE_GLOBAL_ADMIN_COMMUNITY_READ =
'credentialRuleTypes-spaceGlobalAdminCommunityRead';
export const CREDENTIAL_RULE_TYPES_ACCOUNT_MANAGE =
'credentialRuleTypes-accountManage';
export const CREDENTIAL_RULE_TYPES_ACCOUNT_CHILD_ENTITIES =
'credentialRuleTypes-accountChildEntities';
export const CREDENTIAL_RULE_TYPES_SPACE_GLOBAL_COMMUNITY_READ =
'credentialRuleTypes-spaceGlobalCommunityRead';
export const CREDENTIAL_RULE_TYPES_SPACE_PLATFORM_SETTINGS =
'credentialRuleTypes-spacePlatformSettings';
export const CREDENTIAL_RULE_TYPES_SPACE_READ =
export const CREDENTIAL_RULE_TYPES_GLOBAL_SPACE_READ =
'credentialRuleTypes-spaceGlobalRead';
export const CREDENTIAL_RULE_TYPES_SPACE_AUTHORIZATION_GLOBAL_ADMIN_GRANT =
'credentialRuleTypes-spaceAuthorizationGlobalAdminGrant';
export const CREDENTIAL_RULE_TYPES_SPACE_COMMUNITY_APPLY_GLOBAL_REGISTERED =
'credentialRuleTypes-spaceCommunityApplyGlobalRegistered';
export const CREDENTIAL_RULE_TYPES_SPACE_COMMUNITY_JOIN_GLOBAL_REGISTERED =
Expand Down Expand Up @@ -70,8 +70,6 @@ export const CREDENTIAL_RULE_TYPES_PLATFORM_ANY_ADMIN =
'credentialRuleTypes-platformAnyAdmin';
export const CREDENTIAL_RULE_PLATFORM_CREATE_ORGANIZATION =
'credentialRuleTypes-platformCreateOrganization';
export const CREDENTIAL_RULE_ACCOUNT_CREATE_VIRTUAL_CONTRIBUTOR =
'credentialRuleTypes-accountCreateVirtualContributor';
export const CREDENTIAL_RULE_PLATFORM_CREATE_SPACE =
'credentialRuleTypes-platformCreateSpace';
export const CREDENTIAL_RULE_TYPES_PLATFORM_ACCESS_GUIDANCE =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export const POLICY_RULE_SPACE_CREATE_SUBSPACE =
'policyRule-spaceCreateSubspace';
export const POLICY_RULE_WHITEBOARD_CONTENT_UPDATE =
'policyRule-whiteboardContentUpdate';
export const POLICY_RULE_ACCOUNT_CREATE_VC = 'policyRule-accountCreateVC';
export const POLICY_RULE_VISUAL_UPDATE = 'policyRule-visualUpdate';
export const POLICY_RULE_ROOM_CONTRIBUTE = 'policyRule-roomContribute';
export const POLICY_RULE_ROOM_ADMINS = 'policyRule-roomAdminsCreate';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@ import { Injectable } from '@nestjs/common';
import { ICommunication } from '@domain/communication/communication';
import { AuthorizationPolicyService } from '@domain/common/authorization-policy/authorization.policy.service';
import { IAuthorizationPolicy } from '@domain/common/authorization-policy/authorization.policy.interface';
import { AuthorizationPrivilege, LogContext } from '@common/enums';
import { CommunicationService } from './communication.service';
import { AuthorizationPolicyRulePrivilege } from '@core/authorization/authorization.policy.rule.privilege';
import {
POLICY_RULE_FORUM_CONTRIBUTE,
POLICY_RULE_FORUM_CREATE,
} from '@common/constants';
import { RoomAuthorizationService } from '../room/room.service.authorization';
import { RelationshipNotFoundException } from '@common/exceptions/relationship.not.found.exception';
import { LogContext } from '@common/enums/logging.context';

@Injectable()
export class CommunicationAuthorizationService {
Expand Down Expand Up @@ -49,10 +44,6 @@ export class CommunicationAuthorizationService {
parentAuthorization
);

communication.authorization = this.appendPrivilegeRules(
communication.authorization
);

communication.updates =
this.roomAuthorizationService.applyAuthorizationPolicy(
communication.updates,
Expand All @@ -66,29 +57,4 @@ export class CommunicationAuthorizationService {

return communication;
}

private appendPrivilegeRules(
authorization: IAuthorizationPolicy
): IAuthorizationPolicy {
const privilegeRules: AuthorizationPolicyRulePrivilege[] = [];

// Allow any contributor to this community to create discussions, and to send messages to the discussion
const contributePrivilege = new AuthorizationPolicyRulePrivilege(
[AuthorizationPrivilege.CREATE_DISCUSSION],
AuthorizationPrivilege.CONTRIBUTE,
POLICY_RULE_FORUM_CONTRIBUTE
);
privilegeRules.push(contributePrivilege);

const createPrivilege = new AuthorizationPolicyRulePrivilege(
[AuthorizationPrivilege.CREATE_DISCUSSION],
AuthorizationPrivilege.CREATE,
POLICY_RULE_FORUM_CREATE
);
privilegeRules.push(createPrivilege);
return this.authorizationPolicyService.appendPrivilegeAuthorizationRules(
authorization,
privilegeRules
);
}
}
11 changes: 10 additions & 1 deletion src/domain/community/community/community.resolver.mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,9 +314,18 @@ export class CommunityResolverMutations {
roleData.communityID
);

// Extend the authorization policy with a credential rule to assign the GRANT privilege
// to the user with rights around the incoming virtual being removed.
//. Then if it is the user that is logged in then the user will have the GRANT privilege + so can carry out the mutation
const extendedAuthorization =
await this.communityAuthorizationService.extendAuthorizationPolicyForVirtualContributorRemoval(
community,
roleData.virtualContributorID
);

await this.authorizationService.grantAccessOrFail(
agentInfo,
community.authorization,
extendedAuthorization,
AuthorizationPrivilege.GRANT,
`remove virtual from community role: ${community.id}`
);
Expand Down
36 changes: 36 additions & 0 deletions src/domain/community/community/community.service.authorization.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
CREDENTIAL_RULE_TYPES_COMMUNITY_INVITE_MEMBERS,
POLICY_RULE_COMMUNITY_ADD_VC,
POLICY_RULE_COMMUNITY_INVITE_MEMBER,
CREDENTIAL_RULE_COMMUNITY_VIRTUAL_CONTRIBUTOR_REMOVAL,
} from '@common/constants';
import { InvitationAuthorizationService } from '../invitation/invitation.service.authorization';
import { RelationshipNotFoundException } from '@common/exceptions/relationship.not.found.exception';
Expand All @@ -34,6 +35,7 @@ import { LicensePrivilege } from '@common/enums/license.privilege';
import { AuthorizationPolicyRulePrivilege } from '@core/authorization/authorization.policy.rule.privilege';
import { IAgent } from '@domain/agent';
import { PlatformInvitationAuthorizationService } from '@platform/invitation/platform.invitation.service.authorization';
import { VirtualContributorService } from '../virtual-contributor/virtual.contributor.service';

@Injectable()
export class CommunityAuthorizationService {
Expand All @@ -46,6 +48,7 @@ export class CommunityAuthorizationService {
private applicationAuthorizationService: ApplicationAuthorizationService,
private invitationAuthorizationService: InvitationAuthorizationService,
private communityPolicyService: CommunityPolicyService,
private virtualContributorService: VirtualContributorService,
private platformInvitationAuthorizationService: PlatformInvitationAuthorizationService,
private communityGuidelinesAuthorizationService: CommunityGuidelinesAuthorizationService
) {}
Expand Down Expand Up @@ -302,6 +305,39 @@ export class CommunityAuthorizationService {
return updatedAuthorization;
}

public async extendAuthorizationPolicyForVirtualContributorRemoval(
community: ICommunity,
virtualContributorToBeRemoved: string
): Promise<IAuthorizationPolicy> {
const newRules: IAuthorizationPolicyRuleCredential[] = [];

const accountHostCredentials =
await this.virtualContributorService.getAccountHostCredentials(
virtualContributorToBeRemoved
);

const userSelfRemovalRule =
this.authorizationPolicyService.createCredentialRule(
[AuthorizationPrivilege.GRANT],
accountHostCredentials,
CREDENTIAL_RULE_COMMUNITY_VIRTUAL_CONTRIBUTOR_REMOVAL
);
newRules.push(userSelfRemovalRule);

const clonedCommunityAuthorization =
this.authorizationPolicyService.cloneAuthorizationPolicy(
community.authorization
);

const updatedAuthorization =
this.authorizationPolicyService.appendCredentialAuthorizationRules(
clonedCommunityAuthorization,
newRules
);

return updatedAuthorization;
}

private appendPrivilegeRules(
authorization: IAuthorizationPolicy
): IAuthorizationPolicy {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export class VirtualContributorAuthorizationService {
);
newRules.push(globalCommunityRead);

// TODO: rule that for now allows global support ability to manage VCs, this to be removed later
const globalSupportManage =
this.authorizationPolicyService.createCredentialRuleUsingTypesOnly(
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { IMessageAnswerToQuestion } from '@domain/communication/message.answer.t
import { IAiPersona } from '../ai-persona';
import { IContributor } from '../contributor/contributor.interface';
import { AccountHostService } from '@domain/space/account.host/account.host.service';
import { ICredentialDefinition } from '@domain/agent/credential/credential.definition.interface';

@Injectable()
export class VirtualContributorService {
Expand Down Expand Up @@ -457,6 +458,26 @@ export class VirtualContributorService {
return host;
}

public async getAccountHostCredentials(
virtualContributorID: string
): Promise<ICredentialDefinition[]> {
const virtualContributorWithAccount =
await this.getVirtualContributorOrFail(virtualContributorID, {
relations: { account: true },
});
const account = virtualContributorWithAccount.account;
if (!account)
throw new EntityNotInitializedException(
`Virtual Contributor Account not initialized: ${virtualContributorID}`,
LogContext.AUTH
);

const hostCredentials = await this.accountHostService.getHostCredentials(
account
);
return hostCredentials;
}

async getAiPersonaOrFail(
virtualContributor: IVirtualContributor
): Promise<IAiPersona> {
Expand Down
2 changes: 2 additions & 0 deletions src/domain/space/account/account.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { LicenseIssuerModule } from '@platform/license-issuer/license.issuer.mod
import { AccountHostModule } from '../account.host/account.host.module';
import { LicenseEngineModule } from '@core/license-engine/license.engine.module';
import { StorageAggregatorModule } from '@domain/storage/storage-aggregator/storage.aggregator.module';
import { CommunityPolicyModule } from '@domain/community/community-policy/community.policy.module';

@Module({
imports: [
Expand All @@ -43,6 +44,7 @@ import { StorageAggregatorModule } from '@domain/storage/storage-aggregator/stor
LicenseIssuerModule,
LicenseEngineModule,
NameReporterModule,
CommunityPolicyModule,
TypeOrmModule.forFeature([Account]),
],
providers: [
Expand Down
48 changes: 6 additions & 42 deletions src/domain/space/account/account.resolver.mutations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ import { IVirtualContributor } from '@domain/community/virtual-contributor/virtu
import { CreateVirtualContributorOnAccountInput } from './dto/account.dto.create.virtual.contributor';
import { VirtualContributorAuthorizationService } from '@domain/community/virtual-contributor/virtual.contributor.service.authorization';
import { VirtualContributorService } from '@domain/community/virtual-contributor/virtual.contributor.service';
import { IngestSpaceInput } from '../space/dto/space.dto.ingest';
import { EventBus } from '@nestjs/cqrs';
import { IngestSpace } from '@services/infrastructure/event-bus/commands';
import { CommunityContributorType } from '@common/enums/community.contributor.type';
import { CommunityRole } from '@common/enums/community.role';
import { CreateSpaceOnAccountInput } from './dto/account.dto.create.space';
Expand All @@ -47,8 +44,7 @@ export class AccountResolverMutations {
private virtualContributorAuthorizationService: VirtualContributorAuthorizationService,
private spaceDefaultsService: SpaceDefaultsService,
private namingReporter: NameReporterService,
private spaceService: SpaceService,
private eventBus: EventBus
private spaceService: SpaceService
) {}

@UseGuards(GraphqlGuard)
Expand Down Expand Up @@ -175,7 +171,7 @@ export class AccountResolverMutations {
@CurrentUser() agentInfo: AgentInfo,
@Args('updateData') updateData: UpdateAccountPlatformSettingsInput
): Promise<IAccount> {
const account = await this.accountService.getAccountOrFail(
let account = await this.accountService.getAccountOrFail(
updateData.accountID
);
this.authorizationService.grantAccessOrFail(
Expand All @@ -192,9 +188,10 @@ export class AccountResolverMutations {
await this.accountService.save(result);

// Update the authorization policy as most of the changes imply auth policy updates
return this.accountAuthorizationService
.applyAuthorizationPolicy(result)
.then(account => this.accountService.save(account));
account = await this.accountAuthorizationService.applyAuthorizationPolicy(
result
);
return await this.accountService.save(account);
}

@UseGuards(GraphqlGuard)
Expand Down Expand Up @@ -303,37 +300,4 @@ export class AccountResolverMutations {
virtual.id
);
}

@UseGuards(GraphqlGuard)
@Mutation(() => ISpace, {
description: 'Triggers space ingestion.',
})
async ingestSpace(
@CurrentUser() agentInfo: AgentInfo,
@Args('ingestSpaceData')
ingestSpaceData: IngestSpaceInput
): Promise<ISpace> {
const space = await this.spaceService.getSpaceOrFail(
ingestSpaceData.spaceID,
{
relations: {
account: {
defaults: {
authorization: true,
},
},
},
}
);

this.authorizationService.grantAccessOrFail(
agentInfo,
space.account.authorization,
AuthorizationPrivilege.PLATFORM_ADMIN,
`ingest space: ${space.nameID}(${space.id})`
);

this.eventBus.publish(new IngestSpace(space.id, ingestSpaceData.purpose));
return space;
}
}
Loading

0 comments on commit 2ea98a7

Please sign in to comment.