fix: requested changes

This commit is contained in:
Daniel Hougaard
2025-04-25 05:22:17 +04:00
parent f5fa57d6c5
commit 50679ba29d
16 changed files with 184 additions and 127 deletions
@@ -276,23 +276,27 @@ export class TeamsBot extends TeamsActivityHandler {
const botWasAdded = membersAdded.some((member) => member.id === context.activity.recipient.id);
if (botWasAdded && context.activity.conversation.tenantId) {
const microsoftTeamIntegration = await this.microsoftTeamsIntegrationDAL.findOne({
tenantId: context.activity.conversation.tenantId
});
const microsoftTeamIntegration = await this.microsoftTeamsIntegrationDAL
.findOne({
tenantId: context.activity.conversation.tenantId
})
.catch(() => null);
await this.workflowIntegrationDAL
.update(
{
id: microsoftTeamIntegration.id,
status: WorkflowIntegrationStatus.PENDING
},
{
status: WorkflowIntegrationStatus.INSTALLED
}
)
.catch((error) => {
logger.error(error, "Microsoft Teams Workflow Integration: Failed to update workflow integration");
});
if (microsoftTeamIntegration) {
await this.workflowIntegrationDAL
.update(
{
id: microsoftTeamIntegration.id,
status: WorkflowIntegrationStatus.PENDING
},
{
status: WorkflowIntegrationStatus.INSTALLED
}
)
.catch((error) => {
logger.error(error, "Microsoft Teams Workflow Integration: Failed to update workflow integration");
});
}
// This is required in order for the bot to send proactive messages, which is required for the bot to pass the bot release validation step.
await context.sendActivity(
@@ -308,47 +312,55 @@ export class TeamsBot extends TeamsActivityHandler {
}
async sendMessageToChannel(tenantId: string, channelId: string, teamId: string, notification: TNotification) {
const { adaptiveCard } = buildTeamsPayload(notification);
try {
const { adaptiveCard } = buildTeamsPayload(notification);
const botToken = await getMicrosoftTeamsAccessToken({
tenantId,
clientId: this.botAppId,
clientSecret: this.botAppPassword,
getBotFrameworkToken: true
});
const botToken = await getMicrosoftTeamsAccessToken({
tenantId,
clientId: this.botAppId,
clientSecret: this.botAppPassword,
getBotFrameworkToken: true
});
const adaptiveCardActivity = {
type: "message",
attachments: [
{
contentType: "application/vnd.microsoft.card.adaptive",
content: adaptiveCard
}
],
conversation: {
id: channelId,
isGroup: true
},
channelData: {
channel: {
id: channelId
const adaptiveCardActivity = {
type: "message",
attachments: [
{
contentType: "application/vnd.microsoft.card.adaptive",
content: adaptiveCard
}
],
conversation: {
id: channelId,
isGroup: true
},
team: {
id: teamId
channelData: {
channel: {
id: channelId
},
team: {
id: teamId
}
}
}
};
};
await axios.post(
`https://smba.trafficmanager.net/amer/v3/conversations/${channelId}/activities`,
adaptiveCardActivity,
{
headers: {
Authorization: `Bearer ${botToken}`,
"Content-Type": "application/json"
await axios.post(
`https://smba.trafficmanager.net/amer/v3/conversations/${channelId}/activities`,
adaptiveCardActivity,
{
headers: {
Authorization: `Bearer ${botToken}`,
"Content-Type": "application/json"
}
}
}
);
);
} catch (error) {
logger.error(
error,
`sendMessageToChannel: Microsoft Teams Workflow Integration: Failed to send message to channel [channelId=${channelId}] [teamId=${teamId}] [tenantId=${tenantId}]`
);
throw error;
}
}
// todo: filter out teams that the bot is not a member of
@@ -429,7 +441,7 @@ export class TeamsBot extends TeamsActivityHandler {
}
}
export const MicrosoftTeamsChannelsSchema = z
export const validateMicrosoftTeamsChannelsSchema = z
.object({
teamId: z.string(),
channelIds: z.array(z.string()).min(1)
@@ -23,7 +23,7 @@ import { TMicrosoftTeamsIntegrationDALFactory } from "./microsoft-teams-integrat
import {
TCheckInstallationStatusDTO,
TCreateMicrosoftTeamsIntegrationDTO,
TDeleteMicrosoftTeamsIntegrationIntegrationDTO,
TDeleteMicrosoftTeamsIntegrationDTO,
TGetMicrosoftTeamsIntegrationByIdDTO,
TGetMicrosoftTeamsIntegrationByOrgDTO,
TGetTeamsDTO,
@@ -424,7 +424,7 @@ export const microsoftTeamsServiceFactory = ({
actorOrgId,
actorAuthMethod,
id
}: TDeleteMicrosoftTeamsIntegrationIntegrationDTO) => {
}: TDeleteMicrosoftTeamsIntegrationDTO) => {
const microsoftTeamsIntegration = await microsoftTeamsIntegrationDAL.findByIdWithWorkflowIntegrationDetails(id);
if (!microsoftTeamsIntegration) {
throw new NotFoundError({
@@ -22,7 +22,7 @@ export type TGetTeamsDTO = Omit<TOrgPermission, "orgId"> & {
workflowIntegrationId: string;
};
export type TDeleteMicrosoftTeamsIntegrationIntegrationDTO = {
export type TDeleteMicrosoftTeamsIntegrationDTO = {
id: string;
} & Omit<TOrgPermission, "orgId">;
@@ -43,7 +43,7 @@ import { TIdentityOrgDALFactory } from "../identity/identity-org-dal";
import { TIdentityProjectDALFactory } from "../identity-project/identity-project-dal";
import { TIdentityProjectMembershipRoleDALFactory } from "../identity-project/identity-project-membership-role-dal";
import { TKmsServiceFactory } from "../kms/kms-service";
import { MicrosoftTeamsChannelsSchema } from "../microsoft-teams/microsoft-teams-fns";
import { validateMicrosoftTeamsChannelsSchema } from "../microsoft-teams/microsoft-teams-fns";
import { TMicrosoftTeamsIntegrationDALFactory } from "../microsoft-teams/microsoft-teams-integration-dal";
import { TProjectMicrosoftTeamsConfigDALFactory } from "../microsoft-teams/project-microsoft-teams-config-dal";
import { TOrgDALFactory } from "../org/org-dal";
@@ -1407,6 +1407,10 @@ export const projectServiceFactory = ({
integrationId: config.microsoftTeamsIntegrationId
};
}
throw new BadRequestError({
message: `Integration type '${integration as string}' not supported`
});
};
const updateProjectWorkflowIntegration = async ({
@@ -1526,9 +1530,6 @@ export const projectServiceFactory = ({
});
}
const sanitizedAccessRequestChannels = MicrosoftTeamsChannelsSchema.parse(accessRequestChannels);
const sanitizedSecretRequestChannels = MicrosoftTeamsChannelsSchema.parse(secretRequestChannels);
const microsoftTeamsIntegration =
await microsoftTeamsIntegrationDAL.findByIdWithWorkflowIntegrationDetails(integrationId);
@@ -1538,6 +1539,32 @@ export const projectServiceFactory = ({
});
}
if (microsoftTeamsIntegration.orgId !== actorOrgId) {
throw new ForbiddenRequestError({
message: "Selected Microsoft Teams integration is not in the same organization"
});
}
const { permission } = await permissionService.getProjectPermission({
actor,
actorId,
projectId,
actorAuthMethod,
actorOrgId,
actionProjectType: ActionProjectType.Any
});
ForbiddenError.from(permission).throwUnlessCan(ProjectPermissionActions.Edit, ProjectPermissionSub.Settings);
if (microsoftTeamsIntegration.orgId !== project.orgId) {
throw new ForbiddenRequestError({
message: "Selected Microsoft Teams integration is not in the same organization"
});
}
const sanitizedAccessRequestChannels = validateMicrosoftTeamsChannelsSchema.parse(accessRequestChannels);
const sanitizedSecretRequestChannels = validateMicrosoftTeamsChannelsSchema.parse(secretRequestChannels);
const updatedWorkflowIntegration = await projectMicrosoftTeamsConfigDAL.transaction(async (tx) => {
const microsoftTeamsConfig = await projectMicrosoftTeamsConfigDAL.findOne(
{
+19 -8
View File
@@ -164,14 +164,25 @@ export type TGetProjectWorkflowIntegrationConfig = TProjectPermission & {
integration: WorkflowIntegration;
};
export type TUpdateProjectWorkflowIntegration = {
integrationId: string;
integration: WorkflowIntegration;
isAccessRequestNotificationEnabled: boolean;
accessRequestChannels?: string | { teamId: string; channelIds: string[] };
isSecretRequestNotificationEnabled: boolean;
secretRequestChannels?: string | { teamId: string; channelIds: string[] };
} & TProjectPermission;
export type TUpdateProjectWorkflowIntegration = (
| {
integrationId: string;
integration: WorkflowIntegration.SLACK;
isAccessRequestNotificationEnabled: boolean;
isSecretRequestNotificationEnabled: boolean;
accessRequestChannels?: string;
secretRequestChannels?: string;
}
| {
integrationId: string;
integration: WorkflowIntegration.MICROSOFT_TEAMS;
isAccessRequestNotificationEnabled: boolean;
isSecretRequestNotificationEnabled: boolean;
accessRequestChannels?: { teamId: string; channelIds: string[] };
secretRequestChannels?: { teamId: string; channelIds: string[] };
}
) &
TProjectPermission;
export type TDeleteProjectWorkflowIntegration = {
integrationId: string;