Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 24x 24x 24x 24x 1x 1x 1x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 16x 8x 8x 8x 8x 8x 6x 6x 6x 16x 16x 1x 1x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 6x 1x 1x 16x 16x 16x 16x 1x | import { ForbiddenException, Logger, NotFoundException, UnprocessableEntityException } from '@nestjs/common';
import { EventBus } from '@nestjs/cqrs';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Transactional } from 'typeorm-transactional';
import { Team, type Company } from '@amalia/core/models';
import { assert, toError } from '@amalia/ext/typescript';
import { canModifyTeams, defineAbilityFor } from '@amalia/kernel/auth/shared';
import { type AuthenticatedContext } from '@amalia/kernel/auth/types';
import { RecordObject, RecordType } from '@amalia/tenants/monitoring/audit/types';
import { TeamUpdatedEvent } from '../events/team-updated-event';
export class UnlinkFromParentTeamUseCase {
private readonly logger = new Logger(UnlinkFromParentTeamUseCase.name);
public constructor(
private readonly eventBus: EventBus,
@InjectRepository(Team)
private readonly teamsRepository: Repository<Team>,
) {}
@Transactional()
public async execute({
company,
authenticatedContext,
teamId,
}: {
company: Company;
authenticatedContext: AuthenticatedContext;
teamId: Team['id'];
}) {
this.assertCanExecute(authenticatedContext);
const team = await this.teamsRepository.findOne({
where: { id: teamId, company: { id: company.id } },
relations: ['parentTeam'],
select: {
id: true,
name: true,
parentTeamId: true,
parentTeam: { id: true, name: true },
},
});
assert(team, new NotFoundException(`Team ${teamId} not found`));
assert(team.parentTeam, new UnprocessableEntityException(`Team ${team.name} has no parent`));
await this.teamsRepository.save({ id: teamId, parentTeamId: null, parentTeam: undefined });
try {
await this.publishAuditLog({ authenticatedContext, team });
} catch (err) {
this.logger.error({
message: 'Failed to publish TeamUpdatedEvent',
error: toError(err),
team,
});
}
}
private async publishAuditLog({
authenticatedContext,
team,
}: {
authenticatedContext: AuthenticatedContext;
team: Pick<Team, 'id' | 'name' | 'parentTeam'>;
}) {
assert(team.parentTeam, 'Parent team should be defined here');
await this.eventBus.publish(
new TeamUpdatedEvent({
authenticatedContext,
object: RecordObject.TEAM,
type: RecordType.EDIT,
values: {
target: { id: team.id, name: team.name },
oldValues: { parentTeam: team.parentTeam.name },
newValues: { parentTeam: null },
},
}),
);
}
private assertCanExecute(authenticatedContext: AuthenticatedContext) {
const ability = defineAbilityFor(authenticatedContext);
assert(canModifyTeams(ability), new ForbiddenException('You do not have the permission to modify teams'));
}
}
|