Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
jessicamcinchak committed Jul 28, 2024
1 parent b9db834 commit 5acb022
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import supertest from "supertest";
import app from "../../../../server";
import SlackNotify from "slack-notify";
import { BOPSBody, EmailBody, S3Body, UniformBody } from "./types";
import { BOPSBody, EmailBody, FlowStatusBody, S3Body, UniformBody } from "./types";
import { $api } from "../../../../client";
import { CoreDomainClient } from "@opensystemslab/planx-core";

Expand Down Expand Up @@ -399,4 +399,63 @@ describe("Send Slack notifications endpoint", () => {
});
});
});

describe("Flow status update notification", () => {
const body: FlowStatusBody = {
event: {
data: {
new: {
status: "online",
id: "flow-123"
}
}
}
};

it("skips the staging environment", async () => {
process.env.APP_ENVIRONMENT = "staging";
await post(ENDPOINT)
.query({ type: "flow-status" })
.set({ Authorization: process.env.HASURA_PLANX_API_KEY! })
.send(body)
.expect(200)
.then((response) => {
expect(response.body.message).toMatch(/skipping Slack notification/);
});
});

it("posts to Slack on success", async () => {
process.env.APP_ENVIRONMENT = "production";

await post(ENDPOINT)
.query({ type: "flow-status" })
.set({ Authorization: process.env.HASURA_PLANX_API_KEY! })
.send(body)
.expect(200)
.then((response) => {
expect(SlackNotify).toHaveBeenCalledWith(
process.env.SLACK_WEBHOOK_URL,
);
expect(mockSend).toHaveBeenCalledTimes(1);
expect(response.body.message).toBe("Posted to Slack");
expect(response.body.data).toMatch(/online/);
expect(response.body.data).toMatch(/flow-123/);
});
});

it("returns error when Slack fails", async () => {
process.env.APP_ENVIRONMENT = "production";
mockSend.mockRejectedValue("Fail!");

await post(ENDPOINT)
.query({ type: "flow-status" })
.set({ Authorization: process.env.HASURA_PLANX_API_KEY! })
.send(body)
.expect(500)
.then((response) => {
expect(mockSend).toHaveBeenCalledTimes(1);
expect(response.body.error).toMatch(/Failed to send/);
});
});
});
});
21 changes: 20 additions & 1 deletion api.planx.uk/modules/webhooks/service/sendNotification/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
EmailEventData,
EventData,
EventType,
FlowStatusEventData,
S3EventData,
UniformEventData,
} from "./types";
Expand All @@ -16,14 +17,15 @@ export const sendSlackNotification = async (
) => {
const slack = SlackNotify(process.env.SLACK_WEBHOOK_URL!);
let message = getMessageForEventType(data, type);
let emoji = getEmojiForEventType(type, data);

const sessionId = getSessionIdFromEvent(data, type);
const { disability, resubmission } =
await getExemptionStatusesForSession(sessionId);
if (disability) message += " [Exempt]";
if (resubmission) message += " [Resubmission]";

await slack.send(":incoming_envelope: " + message);
await slack.send(emoji + " " + message);
return message;
};

Expand All @@ -47,14 +49,31 @@ const getMessageForEventType = (data: EventData, type: EventType) => {
const { session_id, team_slug } = data as S3EventData;
return `New S3 + Power Automate submission *${session_id}* [${team_slug}]`;
}

if (type === "flow-status") {
const { id, status } = data as FlowStatusEventData;
return `*${team_slug}/${flow_slug}* is now *${status}* (${id})`;
}
};

const getEmojiForEventType = (type: EventType, data?: EventType) => {
if (type.endsWith("-submission")) {
return ":incoming_message:"
}

if (type === "flow-status") {
const { id, status } = data as FlowStatusEventData;
return status === "online" ? ":large_green_cirlce:" : ":no_entry:";
}
}

const getSessionIdFromEvent = (data: EventData, type: EventType) =>
({
"bops-submission": (data as BOPSEventData).session_id,
"uniform-submission": (data as UniformEventData).payload?.sessionId,
"email-submission": (data as EmailEventData).session_id,
"s3-submission": (data as S3EventData).session_id,
"flow-status": (data as FlowStatusEventData).id,
})[type];

const getExemptionStatusesForSession = async (sessionId: string) => {
Expand Down
16 changes: 16 additions & 0 deletions api.planx.uk/modules/webhooks/service/sendNotification/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ export const s3SubmissionSchema = z.object({
}),
});

export const flowStatusSchema = z.object({
body: z.object({
event: z.object({
data: z.object({
new: z.object({
id: z.string(),
status: z.string(),
}),
}),
}),
}),
query: z.object({
type: z.literal("flow-status"),
}),
});

export const sendSlackNotificationSchema = z.union([
bopsSubmissionSchema,
uniformSubmissionSchema,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ValidatedRequestHandler } from "../../../../shared/middleware/validate"
import {
bopsSubmissionSchema,
emailSubmissionSchema,
flowStatusSchema,
s3SubmissionSchema,
sendSlackNotificationSchema,
uniformSubmissionSchema,
Expand All @@ -29,11 +30,15 @@ export type EmailEventData = EmailBody["event"]["data"]["new"];
export type S3Body = z.infer<typeof s3SubmissionSchema>["body"];
export type S3EventData = S3Body["event"]["data"]["new"];

export type FlowStatusBody = z.infer<typeof flowStatusSchema>["body"];
export type FlowStatusEventData = FlowStatusBody["event"]["data"]["new"];

export type EventData =
| BOPSEventData
| UniformEventData
| EmailEventData
| S3EventData;
| S3EventData
| FlowStatusEventData;

export type SendSlackNotification = ValidatedRequestHandler<
typeof sendSlackNotificationSchema,
Expand Down
31 changes: 31 additions & 0 deletions hasura.planx.uk/metadata/tables.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,37 @@
_eq: x-hasura-user-id
- role:
_eq: teamEditor
event_triggers:
- name: setup_flow_status_notifications
definition:
enable_manual: false
update:
columns:
- status
retry_conf:
interval_sec: 30
num_retries: 1
timeout_sec: 60
webhook_from_env: HASURA_PLANX_API_URL
headers:
- name: authorization
value_from_env: HASURA_PLANX_API_KEY
request_transform:
body:
action: transform
template: |-
{
"table": {
"name": {{$body.table.name}},
"schema": {{$body.table.schema}}
}
}
method: POST
query_params:
type: flow-status
template_engine: Kriti
url: '{{$base_url}}/webhooks/hasura/send-slack-notification'
version: 2
- table:
name: global_settings
schema: public
Expand Down

0 comments on commit 5acb022

Please sign in to comment.