1
Suspend/resume a flow by sending approval URL via email Approval
One script reply has been approved by the moderators Verified

Using gmail resource it sends an email with URL to approval page where you can resume or cancel the flow

Created by mrl5 523 days ago Viewed 3371 times
1
Submitted by mrl5 Deno
Verified 523 days ago
1
import { getResumeUrls } from "https://deno.land/x/windmill@v1.85.0/mod.ts";
2
import { encode as base64UrlEncode } from "https://deno.land/std@0.82.0/encoding/base64url.ts";
3

4
type Gmail = {
5
  token: string;
6
};
7
export async function main(
8
  gmail_auth: Gmail,
9
  approver_emails: string[],
10
  subject = "Resume Windmill flow",
11
) {
12
  throwOnInvalidApprovers(approver_emails);
13

14
  const token = gmail_auth["token"];
15
  const email_promises = approver_emails.map((to_email) =>
16
    sendEmail(token, to_email, subject),
17
  );
18
  const results = await Promise.all(email_promises);
19

20
  return results;
21
}
22

23
async function sendEmail(
24
  gmail_token: string,
25
  to_email: string,
26
  subject: string,
27
): Promise<object> {
28
  const email = await getEmailBody(to_email, subject);
29
  const SEND_EMAIL_URL = `https://gmail.googleapis.com/gmail/v1/users/me/messages/send`;
30
  const body = {
31
    raw: email,
32
  };
33
  const response = await fetch(SEND_EMAIL_URL, {
34
    method: "POST",
35
    body: JSON.stringify(body),
36
    headers: {
37
      Authorization: `Bearer ${gmail_token}`,
38
    },
39
  });
40
  const response_json = await response.json();
41

42
  return handleSendEmailResult(response_json, to_email);
43
}
44

45
async function getEmailBody(to_email: string, subject: string) {
46
  const { approvalPage } = await getResumeUrls(to_email);
47
  const message = `There is a Windmill flow at ${Deno.env.get(
48
    "WM_FLOW_PATH",
49
  )} run by ${Deno.env.get("WM_USERNAME")} waiting for your approval to resume.
50

51
In order to resume or cancel the flow go to ${approvalPage}`;
52
  const email_body = `From: <me>\nTo: <${to_email}>\nSubject: ${subject}\n\r ${message}`;
53

54
  return base64UrlEncode(email_body);
55
}
56

57
function throwOnInvalidApprovers(approvers: string[]) {
58
  if (!Array.isArray(approvers) || approvers.length === 0) {
59
    throw new Error("Expected at least one approver email");
60
  }
61
}
62

63
async function handleSendEmailResult(result: object, to_email: string) {
64
  if (Object.keys(result).includes("error")) {
65
    return Promise.reject({ wm_to_email: to_email, ...result });
66
  }
67

68
  return result;
69
}
70