From 069e07df5eb8987cf5d16662ee95bf019074baf1 Mon Sep 17 00:00:00 2001 From: Sachin Date: Fri, 15 Sep 2023 12:13:56 +0000 Subject: [PATCH 01/16] Email notifications --- radlab-ui/webapp/.env.development | 3 + radlab-ui/webapp/.env.production | 3 + radlab-ui/webapp/package-lock.json | 58 ++++++++++ radlab-ui/webapp/package.json | 3 + .../public/assets/htmlTemplates/email.html | 41 +++++++ .../src/pages/api/deployments/[id]/index.ts | 26 +++++ .../webapp/src/pages/api/deployments/index.ts | 24 ++++ radlab-ui/webapp/src/utils/mailHandler.ts | 109 ++++++++++++++++++ radlab-ui/webapp/src/utils/types.ts | 16 ++- 9 files changed, 282 insertions(+), 1 deletion(-) create mode 100644 radlab-ui/webapp/public/assets/htmlTemplates/email.html create mode 100644 radlab-ui/webapp/src/utils/mailHandler.ts diff --git a/radlab-ui/webapp/.env.development b/radlab-ui/webapp/.env.development index abc0a4a1..23131f8f 100644 --- a/radlab-ui/webapp/.env.development +++ b/radlab-ui/webapp/.env.development @@ -24,3 +24,6 @@ NEXT_PUBLIC_RAD_LAB_DOCS_SITE=https://googlecloudplatform.github.io/rad-lab/ MODULE_DEPLOYMENT_BUCKET_NAME= GIT_TOKEN_SECRET_KEY_NAME=rad-lab-git-access-token + +MAIL_SERVER_USERNAME= +MAIL_SERVER_PASS= diff --git a/radlab-ui/webapp/.env.production b/radlab-ui/webapp/.env.production index 5525ae5d..880082c7 100644 --- a/radlab-ui/webapp/.env.production +++ b/radlab-ui/webapp/.env.production @@ -25,3 +25,6 @@ MODULE_DEPLOYMENT_BUCKET_NAME= GIT_TOKEN_SECRET_KEY_NAME=rad-lab-git-access-token +MAIL_SERVER_USERNAME= +MAIL_SERVER_PASS= + diff --git a/radlab-ui/webapp/package-lock.json b/radlab-ui/webapp/package-lock.json index ab5f0211..59d78802 100644 --- a/radlab-ui/webapp/package-lock.json +++ b/radlab-ui/webapp/package-lock.json @@ -21,6 +21,7 @@ "firebase": "^9.6.5", "firebase-admin": "^11.0.1", "formik": "^2.2.9", + "handlebars": "^4.7.8", "hcl2-parser": "^1.0.3", "lodash": "^4.17.21", "lodash.debounce": "^4.0.8", @@ -28,6 +29,7 @@ "next-i18next": "^10.2.0", "next-seo": "^4.29.0", "next-swagger-doc": "^0.3.4", + "nodemailer": "^6.9.5", "nookies": "^2.5.2", "ramda": "^0.28.0", "react": "^17.0.2", @@ -50,6 +52,7 @@ "@types/lodash.debounce": "^4.0.6", "@types/lunr": "^2.3.4", "@types/node": "^17.0.45", + "@types/nodemailer": "^6.4.10", "@types/ramda": "^0.28.11", "@types/react": "^17.0.38", "@types/uuid": "^8.3.4", @@ -4537,6 +4540,15 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" }, + "node_modules/@types/nodemailer": { + "version": "6.4.10", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.10.tgz", + "integrity": "sha512-oPW/IdhkU3FyZc1dzeqmS+MBjrjZNiiINnrEOrWALzccJlP5xTlbkNr2YnTnnyj9Eqm5ofjRoASEbrCYpA7BrA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/prettier": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", @@ -9030,6 +9042,34 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/handlebars/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/has": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", @@ -12938,6 +12978,11 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, "node_modules/next": { "version": "12.3.4", "resolved": "https://registry.npmjs.org/next/-/next-12.3.4.tgz", @@ -13183,6 +13228,14 @@ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" }, + "node_modules/nodemailer": { + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.5.tgz", + "integrity": "sha512-/dmdWo62XjumuLc5+AYQZeiRj+PRR8y8qKtFCOyuOl1k/hckZd8durUUHs/ucKx6/8kN+wFxqKJlQ/LK/qR5FA==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/nookies": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/nookies/-/nookies-2.5.2.tgz", @@ -17649,6 +17702,11 @@ "node": ">=0.10.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", diff --git a/radlab-ui/webapp/package.json b/radlab-ui/webapp/package.json index 60ecdd5c..51dc1cb6 100644 --- a/radlab-ui/webapp/package.json +++ b/radlab-ui/webapp/package.json @@ -28,6 +28,7 @@ "firebase": "^9.6.5", "firebase-admin": "^11.0.1", "formik": "^2.2.9", + "handlebars": "^4.7.8", "hcl2-parser": "^1.0.3", "lodash": "^4.17.21", "lodash.debounce": "^4.0.8", @@ -35,6 +36,7 @@ "next-i18next": "^10.2.0", "next-seo": "^4.29.0", "next-swagger-doc": "^0.3.4", + "nodemailer": "^6.9.5", "nookies": "^2.5.2", "ramda": "^0.28.0", "react": "^17.0.2", @@ -57,6 +59,7 @@ "@types/lodash.debounce": "^4.0.6", "@types/lunr": "^2.3.4", "@types/node": "^17.0.45", + "@types/nodemailer": "^6.4.10", "@types/ramda": "^0.28.11", "@types/react": "^17.0.38", "@types/uuid": "^8.3.4", diff --git a/radlab-ui/webapp/public/assets/htmlTemplates/email.html b/radlab-ui/webapp/public/assets/htmlTemplates/email.html new file mode 100644 index 00000000..9cef8c41 --- /dev/null +++ b/radlab-ui/webapp/public/assets/htmlTemplates/email.html @@ -0,0 +1,41 @@ + + + + + +

Hello!

+

RAD Lab Module has been successfully deployed for you!

+

Please use below details to access the same.

+ + + + + + + {{#outputs}} + + + + + {{/outputs}} +
Namevalue
{{name}}{{value}}
+ +
+ Thank you
+ GPSDemofactory
+

P.S:- This is an auto generated email!

+ + diff --git a/radlab-ui/webapp/src/pages/api/deployments/[id]/index.ts b/radlab-ui/webapp/src/pages/api/deployments/[id]/index.ts index 999acdff..7fc80eee 100644 --- a/radlab-ui/webapp/src/pages/api/deployments/[id]/index.ts +++ b/radlab-ui/webapp/src/pages/api/deployments/[id]/index.ts @@ -5,12 +5,19 @@ import { } from "@/utils/Api_SeverSideCon" import { mergeVariables, pushPubSubMsg } from "@/utils/api" import { envOrFail } from "@/utils/env" +import { + configureEmailAndSend, + deleteMailHTML, + sendMail, +} from "@/utils/mailHandler" import { withAuth } from "@/utils/middleware" import { AuthedNextApiHandler, DEPLOYMENT_ACTIONS, IDeployment, + IEmailOptions, IPubSubMsg, + IVariables, } from "@/utils/types" import { Timestamp } from "firebase-admin/firestore" import { NextApiResponse } from "next" @@ -98,6 +105,21 @@ const deleteDeployment = async ( await updateByField("deployments", "deploymentId", id, deployment) + const variables = deployment.variables as IVariables + const recipients = [] as string[] + + recipients.push(...variables.trusted_users) + recipients.push(...variables.trusted_groups) + recipients.push(...variables.owner_users) + recipients.push(...variables.owner_groups) + + const mailOptions: IEmailOptions = { + recipients, + subject: "RAD Lab Module is Deleted!", + mailBody: deleteMailHTML(id), + } + await sendMail(mailOptions) + res.status(200).json({ id, deleted: true }) } @@ -156,6 +178,10 @@ const updateDeployment = async ( } await updateByField("deployments", "deploymentId", id, body) const deployments = await getDocsByField("deployments", "deploymentId", id) + + const [upDatedDeployment] = deployments + await configureEmailAndSend(upDatedDeployment) + res.status(200).json({ deployments }) } diff --git a/radlab-ui/webapp/src/pages/api/deployments/index.ts b/radlab-ui/webapp/src/pages/api/deployments/index.ts index 63c64150..8ac24be3 100644 --- a/radlab-ui/webapp/src/pages/api/deployments/index.ts +++ b/radlab-ui/webapp/src/pages/api/deployments/index.ts @@ -7,6 +7,11 @@ import { } from "@/utils/Api_SeverSideCon" import { getBuildStatus, mergeVariables, pushPubSubMsg } from "@/utils/api" import { envOrFail } from "@/utils/env" +import { + configureEmailAndSend, + deleteMailHTML, + sendMail, +} from "@/utils/mailHandler" import { withAuth } from "@/utils/middleware" import { AuthedNextApiHandler, @@ -14,7 +19,9 @@ import { DEPLOYMENT_STATUS, IBuild, IDeployment, + IEmailOptions, IPubSubMsg, + IVariables, } from "@/utils/types" import { Timestamp } from "firebase-admin/firestore" import { NextApiResponse } from "next" @@ -40,6 +47,7 @@ const createDeployment = async ( body.variables = variables body.builds = [] + // @ts-ignore const response: IDeployment = await saveDocument("deployments", body) if (!response) { @@ -67,6 +75,8 @@ const createDeployment = async ( console.error(error) } + await configureEmailAndSend(response) + return res.status(200).json({ response }) } @@ -205,6 +215,20 @@ const deleteDeployment = async ( _nanoseconds: now.nanoseconds, } await updateByField("deployments", "deploymentId", deploymentId, deployment) + + const variables = deployment.variables as IVariables + const recipients = [] as string[] + recipients.push(...variables.trusted_users) + recipients.push(...variables.trusted_groups) + recipients.push(...variables.owner_users) + recipients.push(...variables.owner_groups) + + const mailOptions: IEmailOptions = { + recipients, + subject: "RAD Lab Module is Deleted!", + mailBody: deleteMailHTML(deploymentId), + } + await sendMail(mailOptions) }) return res.status(200).json({ diff --git a/radlab-ui/webapp/src/utils/mailHandler.ts b/radlab-ui/webapp/src/utils/mailHandler.ts new file mode 100644 index 00000000..240691b0 --- /dev/null +++ b/radlab-ui/webapp/src/utils/mailHandler.ts @@ -0,0 +1,109 @@ +import { IDeployment, IEmailOptions } from "@/utils/types" +import { envOrFail } from "@/utils/env" +import nodemailer from "nodemailer" +import { readFileSync } from "fs" +import handlebars from "handlebars" +import path from "path" + +const MAIL_SERVER_USERNAME = envOrFail( + "MAIL_SERVER_USERNAME", + process.env.MAIL_SERVER_USERNAME, +) + +const MAIL_SERVER_PASS = envOrFail( + "MAIL_SERVER_PASS", + process.env.MAIL_SERVER_PASS, +) + +export const configureEmailAndSend = async (deployment: IDeployment) => { + const { variables, projectId, module, deploymentId } = deployment + const recipients = [ + ...variables.trusted_users, + ...variables.trusted_groups, + ...variables.owner_users, + ...variables.owner_groups, + ] as string[] + + const configDirectory = path.resolve(process.cwd(), "public") + + let html = await readFileSync( + path.join(configDirectory + "/assets/htmlTemplates/email.html"), + "utf8", + ) + let template = await handlebars.compile(html) + + const outputs = [ + { + name: "projectId", + value: projectId, + }, + { + name: "module", + value: module, + }, + { + name: "deploymentId", + value: deploymentId, + }, + { + name: "billing_account_id", + value: variables.billing_account_id, + }, + { + name: "zone", + value: variables.zone, + }, + ] + + let data = { + outputs, + } + let htmlToSend = template(data) + + const mailOptions: IEmailOptions = { + recipients, + subject: "RAD Lab Module is Ready!", + mailBody: htmlToSend, + } + + await sendMail(mailOptions) +} + +export const sendMail = async (emailOptions: IEmailOptions) => { + const recipients = emailOptions.recipients + if (!recipients.length) { + return + } + + const uniqueRecipients = recipients.filter( + (item, index) => recipients.indexOf(item) === index, + ) + + let transporter = nodemailer.createTransport({ + service: "gmail", + auth: { + user: MAIL_SERVER_USERNAME, + pass: MAIL_SERVER_PASS, + }, + }) + + transporter.verify().then(console.log).catch(console.error) + + const mailConfiguration = { + from: MAIL_SERVER_USERNAME, + to: uniqueRecipients.toString(), + subject: emailOptions.subject, + html: emailOptions.mailBody, + } + transporter + .sendMail(mailConfiguration) + .then((res) => { + console.log("Mail sent", res) + }) + .catch((error) => { + console.error("Error", error) + }) +} + +export const deleteMailHTML = (deploymentId: string) => + `

Hello!

RAD Lab Module with deployment ID - ${deploymentId} has been successfully deleted!

Thank you
GPSDemofactory

P.S:- This is an auto generated email!

` diff --git a/radlab-ui/webapp/src/utils/types.ts b/radlab-ui/webapp/src/utils/types.ts index aef30ec7..64a3f09b 100644 --- a/radlab-ui/webapp/src/utils/types.ts +++ b/radlab-ui/webapp/src/utils/types.ts @@ -120,7 +120,14 @@ export interface IModuleCard { body: JSX.Element } -const Variables = z.object({}).passthrough() +const Variables = z + .object({ + trusted_users: z.array(z.string()).optional().default([]), + trusted_groups: z.array(z.string()).optional().default([]), + owner_users: z.array(z.string()).optional().default([]), + owner_groups: z.array(z.string()).optional().default([]), + }) + .passthrough() export type IVariables = z.infer export const FirestoreTimestamp = z.object({ @@ -292,3 +299,10 @@ export type CustomNextApiHandler = ( req: AuthedNextApiHandler, res: NextApiResponse, ) => void + +const emailOptions = z.object({ + recipients: z.array(z.string()), + subject: z.string(), + mailBody: z.string(), +}) +export type IEmailOptions = z.infer From 7006df16c885104deb0eb17b3738a975f33d8631 Mon Sep 17 00:00:00 2001 From: Sachin Date: Wed, 20 Sep 2023 14:26:43 +0000 Subject: [PATCH 02/16] email notification changes --- .../assets/htmlTemplates/deleteEmail.html | 20 +++ .../public/assets/htmlTemplates/email.html | 22 ++- .../src/pages/api/deployments/[id]/index.ts | 31 ++-- .../webapp/src/pages/api/deployments/index.ts | 30 ++-- radlab-ui/webapp/src/utils/mailHandler.ts | 139 ++++++++++++------ 5 files changed, 154 insertions(+), 88 deletions(-) create mode 100644 radlab-ui/webapp/public/assets/htmlTemplates/deleteEmail.html diff --git a/radlab-ui/webapp/public/assets/htmlTemplates/deleteEmail.html b/radlab-ui/webapp/public/assets/htmlTemplates/deleteEmail.html new file mode 100644 index 00000000..89d0484b --- /dev/null +++ b/radlab-ui/webapp/public/assets/htmlTemplates/deleteEmail.html @@ -0,0 +1,20 @@ + + + + + +

Hello!

+

+ RAD Lab Module with deployment ID - + + {{deploymentId}} + has been successfully deleted! +

+ +
+ Thank you
+ RAD Lab Admins
+

P.S:- This is an auto generated email. Please do not reply!

+ + diff --git a/radlab-ui/webapp/public/assets/htmlTemplates/email.html b/radlab-ui/webapp/public/assets/htmlTemplates/email.html index 9cef8c41..068249b6 100644 --- a/radlab-ui/webapp/public/assets/htmlTemplates/email.html +++ b/radlab-ui/webapp/public/assets/htmlTemplates/email.html @@ -17,7 +17,7 @@

Hello!

-

RAD Lab Module has been successfully deployed for you!

+

{{mailBodyTitle}}

Please use below details to access the same.

@@ -25,6 +25,22 @@

Hello!

+ + + + + + + + {{#outputs}} @@ -35,7 +51,7 @@

Hello!


Thank you
- GPSDemofactory
-

P.S:- This is an auto generated email!

+ RAD Lab Admins
+

P.S:- This is an auto generated email. Please do not reply!

diff --git a/radlab-ui/webapp/src/pages/api/deployments/[id]/index.ts b/radlab-ui/webapp/src/pages/api/deployments/[id]/index.ts index 7fc80eee..7409356f 100644 --- a/radlab-ui/webapp/src/pages/api/deployments/[id]/index.ts +++ b/radlab-ui/webapp/src/pages/api/deployments/[id]/index.ts @@ -5,19 +5,13 @@ import { } from "@/utils/Api_SeverSideCon" import { mergeVariables, pushPubSubMsg } from "@/utils/api" import { envOrFail } from "@/utils/env" -import { - configureEmailAndSend, - deleteMailHTML, - sendMail, -} from "@/utils/mailHandler" +import { configureEmailAndSend } from "@/utils/mailHandler" import { withAuth } from "@/utils/middleware" import { AuthedNextApiHandler, DEPLOYMENT_ACTIONS, IDeployment, - IEmailOptions, IPubSubMsg, - IVariables, } from "@/utils/types" import { Timestamp } from "firebase-admin/firestore" import { NextApiResponse } from "next" @@ -105,20 +99,10 @@ const deleteDeployment = async ( await updateByField("deployments", "deploymentId", id, deployment) - const variables = deployment.variables as IVariables - const recipients = [] as string[] - - recipients.push(...variables.trusted_users) - recipients.push(...variables.trusted_groups) - recipients.push(...variables.owner_users) - recipients.push(...variables.owner_groups) - - const mailOptions: IEmailOptions = { - recipients, - subject: "RAD Lab Module is Deleted!", - mailBody: deleteMailHTML(id), - } - await sendMail(mailOptions) + await configureEmailAndSend( + "RAD Lab Module has been deleted for you!", + deployment, + ) res.status(200).json({ id, deleted: true }) } @@ -180,7 +164,10 @@ const updateDeployment = async ( const deployments = await getDocsByField("deployments", "deploymentId", id) const [upDatedDeployment] = deployments - await configureEmailAndSend(upDatedDeployment) + await configureEmailAndSend( + "RAD Lab Module has been updated for you!", + upDatedDeployment, + ) res.status(200).json({ deployments }) } diff --git a/radlab-ui/webapp/src/pages/api/deployments/index.ts b/radlab-ui/webapp/src/pages/api/deployments/index.ts index 8ac24be3..993d452e 100644 --- a/radlab-ui/webapp/src/pages/api/deployments/index.ts +++ b/radlab-ui/webapp/src/pages/api/deployments/index.ts @@ -7,11 +7,7 @@ import { } from "@/utils/Api_SeverSideCon" import { getBuildStatus, mergeVariables, pushPubSubMsg } from "@/utils/api" import { envOrFail } from "@/utils/env" -import { - configureEmailAndSend, - deleteMailHTML, - sendMail, -} from "@/utils/mailHandler" +import { configureEmailAndSend } from "@/utils/mailHandler" import { withAuth } from "@/utils/middleware" import { AuthedNextApiHandler, @@ -19,9 +15,7 @@ import { DEPLOYMENT_STATUS, IBuild, IDeployment, - IEmailOptions, IPubSubMsg, - IVariables, } from "@/utils/types" import { Timestamp } from "firebase-admin/firestore" import { NextApiResponse } from "next" @@ -75,7 +69,10 @@ const createDeployment = async ( console.error(error) } - await configureEmailAndSend(response) + await configureEmailAndSend( + "RAD Lab Module has been created for you!", + response, + ) return res.status(200).json({ response }) } @@ -216,19 +213,10 @@ const deleteDeployment = async ( } await updateByField("deployments", "deploymentId", deploymentId, deployment) - const variables = deployment.variables as IVariables - const recipients = [] as string[] - recipients.push(...variables.trusted_users) - recipients.push(...variables.trusted_groups) - recipients.push(...variables.owner_users) - recipients.push(...variables.owner_groups) - - const mailOptions: IEmailOptions = { - recipients, - subject: "RAD Lab Module is Deleted!", - mailBody: deleteMailHTML(deploymentId), - } - await sendMail(mailOptions) + await configureEmailAndSend( + "RAD Lab Module has been deleted for you!", + deployment, + ) }) return res.status(200).json({ diff --git a/radlab-ui/webapp/src/utils/mailHandler.ts b/radlab-ui/webapp/src/utils/mailHandler.ts index 240691b0..e63f2be4 100644 --- a/radlab-ui/webapp/src/utils/mailHandler.ts +++ b/radlab-ui/webapp/src/utils/mailHandler.ts @@ -15,8 +15,18 @@ const MAIL_SERVER_PASS = envOrFail( process.env.MAIL_SERVER_PASS, ) -export const configureEmailAndSend = async (deployment: IDeployment) => { - const { variables, projectId, module, deploymentId } = deployment +const GCP_PROJECT_ID = envOrFail( + "NEXT_PUBLIC_GCP_PROJECT_ID", + process.env.NEXT_PUBLIC_GCP_PROJECT_ID, +) + +export const configureEmailAndSend = async ( + mailSubject: string, + deployment: IDeployment, +) => { + const { variables, projectId, module, deploymentId, deployedByEmail } = + deployment + const recipients = [ ...variables.trusted_users, ...variables.trusted_groups, @@ -24,49 +34,97 @@ export const configureEmailAndSend = async (deployment: IDeployment) => { ...variables.owner_groups, ] as string[] + recipients.push(deployedByEmail) + const configDirectory = path.resolve(process.cwd(), "public") + const server = `https://${GCP_PROJECT_ID}.uc.r.appspot.com` - let html = await readFileSync( - path.join(configDirectory + "/assets/htmlTemplates/email.html"), - "utf8", - ) - let template = await handlebars.compile(html) + if (mailSubject === "RAD Lab Module has been deleted for you!") { + const html = await readFileSync( + path.join(configDirectory + "/assets/htmlTemplates/deleteEmail.html"), + "utf8", + ) + const template = await handlebars.compile(html) - const outputs = [ - { - name: "projectId", - value: projectId, - }, - { - name: "module", - value: module, - }, - { - name: "deploymentId", - value: deploymentId, - }, - { - name: "billing_account_id", - value: variables.billing_account_id, - }, - { - name: "zone", - value: variables.zone, - }, - ] + const data = { + deploymentId, + deploymentLink: `${server}/deployments/${deploymentId}`, + } - let data = { - outputs, - } - let htmlToSend = template(data) + handlebars.registerHelper("deployment_link", () => { + return new handlebars.SafeString( + handlebars.Utils.escapeExpression(data.deploymentLink), + ) + }) - const mailOptions: IEmailOptions = { - recipients, - subject: "RAD Lab Module is Ready!", - mailBody: htmlToSend, - } + const htmlToSend = template(data) + + const mailOptions: IEmailOptions = { + recipients, + subject: mailSubject, + mailBody: htmlToSend, + } - await sendMail(mailOptions) + await sendMail(mailOptions) + } else { + const html = await readFileSync( + path.join(configDirectory + "/assets/htmlTemplates/email.html"), + "utf8", + ) + + const template = await handlebars.compile(html) + + const billingId = variables.billing_account_id as string + + const maskedBillingId = + billingId.substring(0, billingId.length - 6).replace(/[a-z\d]/gi, "*") + + billingId.substring(billingId.length - 6, billingId.length) + + const outputs = [ + { + name: "module", + value: module, + }, + { + name: "billing_account_id", + value: maskedBillingId, + }, + { + name: "zone", + value: variables.zone, + }, + ] + + const data = { + outputs, + mailBodyTitle: mailSubject, + projectId, + projectLink: `https://console.cloud.google.com/welcome?project=${projectId}`, + deploymentId, + deploymentLink: `${server}/deployments/${deploymentId}`, + } + handlebars.registerHelper("gcp_project_link", () => { + return new handlebars.SafeString( + handlebars.Utils.escapeExpression(data.projectLink), + ) + }) + + handlebars.registerHelper("deployment_link", () => { + return new handlebars.SafeString( + handlebars.Utils.escapeExpression(data.deploymentLink), + ) + }) + + const htmlToSend = template(data) + + const mailOptions: IEmailOptions = { + recipients, + subject: mailSubject, + mailBody: htmlToSend, + } + + await sendMail(mailOptions) + } } export const sendMail = async (emailOptions: IEmailOptions) => { @@ -104,6 +162,3 @@ export const sendMail = async (emailOptions: IEmailOptions) => { console.error("Error", error) }) } - -export const deleteMailHTML = (deploymentId: string) => - `

Hello!

RAD Lab Module with deployment ID - ${deploymentId} has been successfully deleted!

Thank you
GPSDemofactory

P.S:- This is an auto generated email!

` From 70c05fea8b0fc242491d102d795b1e731b330b45 Mon Sep 17 00:00:00 2001 From: Sachin Date: Fri, 22 Sep 2023 12:49:07 +0000 Subject: [PATCH 03/16] email notification implementation --- radlab-ui/webapp/.env.development | 3 - radlab-ui/webapp/.env.production | 3 - radlab-ui/webapp/package-lock.json | 2 +- radlab-ui/webapp/package.json | 2 +- .../assets/htmlTemplates/deleteEmail.html | 7 +- .../public/assets/htmlTemplates/email.html | 7 +- .../components/forms/DefaultCreateForm.tsx | 59 ++++++++++++- .../components/forms/DefaultStepCreator.tsx | 20 ++++- radlab-ui/webapp/src/pages/api/secret.ts | 86 +++++++++++++++++++ radlab-ui/webapp/src/utils/data.ts | 19 +++- radlab-ui/webapp/src/utils/mailHandler.ts | 69 ++++++++++----- radlab-ui/webapp/src/utils/types.ts | 19 +++- 12 files changed, 253 insertions(+), 43 deletions(-) create mode 100644 radlab-ui/webapp/src/pages/api/secret.ts diff --git a/radlab-ui/webapp/.env.development b/radlab-ui/webapp/.env.development index 23131f8f..abc0a4a1 100644 --- a/radlab-ui/webapp/.env.development +++ b/radlab-ui/webapp/.env.development @@ -24,6 +24,3 @@ NEXT_PUBLIC_RAD_LAB_DOCS_SITE=https://googlecloudplatform.github.io/rad-lab/ MODULE_DEPLOYMENT_BUCKET_NAME= GIT_TOKEN_SECRET_KEY_NAME=rad-lab-git-access-token - -MAIL_SERVER_USERNAME= -MAIL_SERVER_PASS= diff --git a/radlab-ui/webapp/.env.production b/radlab-ui/webapp/.env.production index 880082c7..5525ae5d 100644 --- a/radlab-ui/webapp/.env.production +++ b/radlab-ui/webapp/.env.production @@ -25,6 +25,3 @@ MODULE_DEPLOYMENT_BUCKET_NAME= GIT_TOKEN_SECRET_KEY_NAME=rad-lab-git-access-token -MAIL_SERVER_USERNAME= -MAIL_SERVER_PASS= - diff --git a/radlab-ui/webapp/package-lock.json b/radlab-ui/webapp/package-lock.json index 59d78802..88a82ed1 100644 --- a/radlab-ui/webapp/package-lock.json +++ b/radlab-ui/webapp/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@google-cloud/iam-credentials": "^2.0.0", "@google-cloud/pubsub": "^3.0.1", - "@google-cloud/secret-manager": "^4.1.3", + "@google-cloud/secret-manager": "^4.2.2", "@google-cloud/storage": "^6.2.3", "@headlessui/react": "^1.4.3", "@heroicons/react": "^1.0.5", diff --git a/radlab-ui/webapp/package.json b/radlab-ui/webapp/package.json index 51dc1cb6..2b5b2e05 100644 --- a/radlab-ui/webapp/package.json +++ b/radlab-ui/webapp/package.json @@ -18,7 +18,7 @@ "dependencies": { "@google-cloud/iam-credentials": "^2.0.0", "@google-cloud/pubsub": "^3.0.1", - "@google-cloud/secret-manager": "^4.1.3", + "@google-cloud/secret-manager": "^4.2.2", "@google-cloud/storage": "^6.2.3", "@headlessui/react": "^1.4.3", "@heroicons/react": "^1.0.5", diff --git a/radlab-ui/webapp/public/assets/htmlTemplates/deleteEmail.html b/radlab-ui/webapp/public/assets/htmlTemplates/deleteEmail.html index 89d0484b..1c4b1dca 100644 --- a/radlab-ui/webapp/public/assets/htmlTemplates/deleteEmail.html +++ b/radlab-ui/webapp/public/assets/htmlTemplates/deleteEmail.html @@ -13,8 +13,11 @@

Hello!


- Thank you
- RAD Lab Admins
+

Thank you

+

P.S:- This is an auto generated email. Please do not reply!

diff --git a/radlab-ui/webapp/public/assets/htmlTemplates/email.html b/radlab-ui/webapp/public/assets/htmlTemplates/email.html index 068249b6..211d7185 100644 --- a/radlab-ui/webapp/public/assets/htmlTemplates/email.html +++ b/radlab-ui/webapp/public/assets/htmlTemplates/email.html @@ -50,8 +50,11 @@

Hello!

Name value
Project Id + {{projectId}} +
Deployment Id + {{deploymentId}} +
{{name}}

- Thank you
- RAD Lab Admins
+

Thank you

+

P.S:- This is an auto generated email. Please do not reply!

diff --git a/radlab-ui/webapp/src/components/forms/DefaultCreateForm.tsx b/radlab-ui/webapp/src/components/forms/DefaultCreateForm.tsx index c3d65b27..9995d493 100644 --- a/radlab-ui/webapp/src/components/forms/DefaultCreateForm.tsx +++ b/radlab-ui/webapp/src/components/forms/DefaultCreateForm.tsx @@ -6,11 +6,13 @@ import { ALERT_TYPE, Dictionary, IFormData, + ISecretManagerReq, IUIVariable, IVariables, } from "@/utils/types" import { mergeAllSafe } from "@/utils/variables" import axios from "axios" +import { FormikValues } from "formik" import { useTranslation } from "next-i18next" import React, { useEffect, useState } from "react" import { useNavigate } from "react-router-dom" @@ -34,9 +36,20 @@ const DefaultCreateForm: React.FC = ({ const setAlert = alertStore((state) => state.setAlert) const user = userStore((state) => state.user) const navigate = useNavigate() + const [answerValueData, setAnswerValueData] = useState({}) const handleSubmit = async (values: IFormData) => { handleLoading(true) + + if (values.email_notifications) { + const secretManagerPayload: ISecretManagerReq = { + key: "mailBoxCred", + value: values.mail_box_password, + } + await saveMailBoxCred(secretManagerPayload) + } + + delete values.mail_box_password const payload = Object.assign(values, { email: user?.email, }) @@ -75,14 +88,55 @@ const DefaultCreateForm: React.FC = ({ return mergeAllSafe([initialFormData, defaultSettingVariables]) } + const saveMailBoxCred = async (payload: ISecretManagerReq) => { + try { + await axios.post("/api/secret", payload) + } catch (error: any) { + setAlert({ + message: error.message, + type: ALERT_TYPE.ERROR, + }) + } + } + + const handleChangeValues = (answerValues: FormikValues) => { + setAnswerValueData(answerValues) + } + + const formatDependsVariables = ( + formVariablesData: IUIVariable[], + currentAnswerValueData: FormikValues, + ) => { + const allNonDependsVars = formVariablesData.filter( + (formVariableData) => + formVariableData.name !== "mail_box_email" && + formVariableData.name !== "mail_box_password", + ) + const allDependsVars = formVariablesData.filter( + (formVariableData) => + formVariableData.name === "mail_box_email" || + formVariableData.name === "mail_box_password", + ) + + const notificationAnswer = currentAnswerValueData.email_notifications + const releventParse = allNonDependsVars.concat( + notificationAnswer ? allDependsVars : [], + ) + return releventParse + } + useEffect(() => { if (formVariables.length > 0) { const initialFormVariable = setDefaultSettingVariables() setInitialData(initialFormVariable) - const groupedVariableList = groupVariables(formVariables) + const releventParse = formatDependsVariables( + formVariables, + answerValueData, + ) + const groupedVariableList = groupVariables(releventParse) setFormData(groupedVariableList) } - }, formVariables) + }, [formVariables, answerValueData]) return (
@@ -98,6 +152,7 @@ const DefaultCreateForm: React.FC = ({ variableList={group} idx={index} key={grpId} + handleChangeValues={handleChangeValues} /> ) : ( <> diff --git a/radlab-ui/webapp/src/components/forms/DefaultStepCreator.tsx b/radlab-ui/webapp/src/components/forms/DefaultStepCreator.tsx index f2f4505c..b52692ae 100644 --- a/radlab-ui/webapp/src/components/forms/DefaultStepCreator.tsx +++ b/radlab-ui/webapp/src/components/forms/DefaultStepCreator.tsx @@ -2,10 +2,14 @@ import sortBy from "lodash/sortBy" import { FormikStep } from "@/components/forms/FormikStepper" import { IUIVariable } from "@/utils/types" import StringField from "@/components/forms/fields/StringField" +import BooleanField from "@/components/forms/fields/BooleanField" +import { useFormikContext } from "formik" +import { useEffect } from "react" interface IDefaultStepCreatorProps { variableList: IUIVariable[] idx: number + handleChangeValues: Function } type IFieldValidateValue = { value: string | number | boolean } @@ -13,6 +17,7 @@ type IFieldValidateValue = { value: string | number | boolean } const DefaultStepCreator: React.FC = ({ variableList, idx, + handleChangeValues, }) => { const sortedList = sortBy(variableList, "order") @@ -24,8 +29,21 @@ const DefaultStepCreator: React.FC = ({ return error } + const { values } = useFormikContext() + + useEffect(() => { + handleChangeValues(values) + }, [values]) + const renderControls = (variable: IUIVariable) => { - return + switch (variable.type) { + case "string": + return + case "bool": + return + default: + return + } } return ( diff --git a/radlab-ui/webapp/src/pages/api/secret.ts b/radlab-ui/webapp/src/pages/api/secret.ts new file mode 100644 index 00000000..bb59d51d --- /dev/null +++ b/radlab-ui/webapp/src/pages/api/secret.ts @@ -0,0 +1,86 @@ +import { NextApiRequest, NextApiResponse } from "next" +import { envOrFail } from "@/utils/env" +import { SecretManagerServiceClient } from "@google-cloud/secret-manager" +import { ISecretManagerReq } from "@/utils/types" + +const secretmanagerClient = new SecretManagerServiceClient() + +const gcpProjectId = envOrFail( + "NEXT_PUBLIC_GCP_PROJECT_ID", + process.env.NEXT_PUBLIC_GCP_PROJECT_ID, +) + +export const getSecretKeyValue = async (secretId: string) => { + try { + const parent = `projects/${gcpProjectId}` + const request = { + name: `${parent}/secrets/${secretId}/versions/latest`, + } + const [response] = await secretmanagerClient.accessSecretVersion(request) + const value = response.payload?.data?.toString() + return value + } catch (error) { + console.error(error) + return null + } +} + +const createSecret = async (req: NextApiRequest, res: NextApiResponse) => { + const { key: secretId, value }: ISecretManagerReq = req.body + + const parent = `projects/${gcpProjectId}` + const secretKeyName = `${parent}/secrets/${secretId}` + + const request = { + parent, + secretId, + secret: { + replication: { + userManaged: { + replicas: [ + { + location: "us-central1", + }, + ], + }, + }, + }, + } + + let runFinally: boolean = true + try { + await secretmanagerClient.createSecret(request) + } catch (error: any) { + // exit finally if exception occures other than secret already exists + if (error.code !== 6) { + runFinally = false + throw new Error("Create secret failed") + } + } finally { + if (runFinally) { + const buff = Buffer.from(value) + const base64Data = buff.toString("base64") + + const versionRequest = { + parent: secretKeyName, + payload: { + data: base64Data, + }, + } + + await secretmanagerClient.addSecretVersion(versionRequest) + } + } + + res.status(200).end() +} + +const handler = async (req: NextApiRequest, res: NextApiResponse) => { + try { + if (req.method === "POST") return await createSecret(req, res) + } catch (error) { + console.error(error) + return res.status(500).end() + } +} +export default handler diff --git a/radlab-ui/webapp/src/utils/data.ts b/radlab-ui/webapp/src/utils/data.ts index 1507b566..6f7dc8b7 100644 --- a/radlab-ui/webapp/src/utils/data.ts +++ b/radlab-ui/webapp/src/utils/data.ts @@ -884,7 +884,24 @@ variable "folder_id" { description = "Folder ID where the project should be created. {{UIMeta group=3 order=1 }}" type = string default = "" -}` +} + +variable "email_notifications" { + description = "Email notifications toggle for enabling email notifications for users. {{UIMeta group=4 order=1 }}" + type = bool + default = false +} +variable "mail_box_email" { + description = "Mail Box Email Id. {{UIMeta group=4 order=2 }}" + type = string + default = "" +} +variable "mail_box_password" { + description = "Mail Box Password. {{UIMeta group=4 order=3 }}" + type = string + default = "" +} +` export const EXAMPLE_CLOUD_BUILD_LOGS = ` starting build "12345678-eeee-4c4c-a94f-abdf234223425" diff --git a/radlab-ui/webapp/src/utils/mailHandler.ts b/radlab-ui/webapp/src/utils/mailHandler.ts index e63f2be4..88b20745 100644 --- a/radlab-ui/webapp/src/utils/mailHandler.ts +++ b/radlab-ui/webapp/src/utils/mailHandler.ts @@ -1,19 +1,12 @@ -import { IDeployment, IEmailOptions } from "@/utils/types" -import { envOrFail } from "@/utils/env" import nodemailer from "nodemailer" import { readFileSync } from "fs" import handlebars from "handlebars" import path from "path" -const MAIL_SERVER_USERNAME = envOrFail( - "MAIL_SERVER_USERNAME", - process.env.MAIL_SERVER_USERNAME, -) - -const MAIL_SERVER_PASS = envOrFail( - "MAIL_SERVER_PASS", - process.env.MAIL_SERVER_PASS, -) +import { getDocsByField } from "@/utils/Api_SeverSideCon" +import { IDeployment, IEmailOptions } from "@/utils/types" +import { envOrFail } from "@/utils/env" +import { getSecretKeyValue } from "@/pages/api/secret" const GCP_PROJECT_ID = envOrFail( "NEXT_PUBLIC_GCP_PROJECT_ID", @@ -26,18 +19,41 @@ export const configureEmailAndSend = async ( ) => { const { variables, projectId, module, deploymentId, deployedByEmail } = deployment + const recipients = [] as string[] + const server = `https://${GCP_PROJECT_ID}.uc.r.appspot.com` - const recipients = [ - ...variables.trusted_users, - ...variables.trusted_groups, - ...variables.owner_users, - ...variables.owner_groups, - ] as string[] + const [settings] = await getDocsByField( + "settings", + "projectId", + GCP_PROJECT_ID, + ) + // verifying email_notifications enabled by admin + if (!settings.variables.email_notifications) { + return + } + //fetch mailbox password from secret manager + const password = await getSecretKeyValue("mailBoxCred") + if (!password) { + return + } + // adding module creator/deployer to recipients list recipients.push(deployedByEmail) + if (variables.trusted_users) { + recipients.push(...variables.trusted_users) + } + if (variables.trusted_groups) { + recipients.push(...variables.trusted_groups) + } + if (variables.owner_users) { + recipients.push(...variables.owner_users) + } + if (variables.owner_groups) { + recipients.push(...variables.owner_groups) + } + const configDirectory = path.resolve(process.cwd(), "public") - const server = `https://${GCP_PROJECT_ID}.uc.r.appspot.com` if (mailSubject === "RAD Lab Module has been deleted for you!") { const html = await readFileSync( @@ -63,6 +79,10 @@ export const configureEmailAndSend = async ( recipients, subject: mailSubject, mailBody: htmlToSend, + credentials: { + email: settings.variables.mail_box_email, + password, + }, } await sendMail(mailOptions) @@ -75,7 +95,6 @@ export const configureEmailAndSend = async ( const template = await handlebars.compile(html) const billingId = variables.billing_account_id as string - const maskedBillingId = billingId.substring(0, billingId.length - 6).replace(/[a-z\d]/gi, "*") + billingId.substring(billingId.length - 6, billingId.length) @@ -121,6 +140,10 @@ export const configureEmailAndSend = async ( recipients, subject: mailSubject, mailBody: htmlToSend, + credentials: { + email: settings.variables.mail_box_email, + password, + }, } await sendMail(mailOptions) @@ -128,7 +151,7 @@ export const configureEmailAndSend = async ( } export const sendMail = async (emailOptions: IEmailOptions) => { - const recipients = emailOptions.recipients + const { recipients, credentials } = emailOptions if (!recipients.length) { return } @@ -140,15 +163,15 @@ export const sendMail = async (emailOptions: IEmailOptions) => { let transporter = nodemailer.createTransport({ service: "gmail", auth: { - user: MAIL_SERVER_USERNAME, - pass: MAIL_SERVER_PASS, + user: credentials.email, + pass: credentials.password, }, }) transporter.verify().then(console.log).catch(console.error) const mailConfiguration = { - from: MAIL_SERVER_USERNAME, + from: credentials.email, to: uniqueRecipients.toString(), subject: emailOptions.subject, html: emailOptions.mailBody, diff --git a/radlab-ui/webapp/src/utils/types.ts b/radlab-ui/webapp/src/utils/types.ts index 64a3f09b..2e201b54 100644 --- a/radlab-ui/webapp/src/utils/types.ts +++ b/radlab-ui/webapp/src/utils/types.ts @@ -122,10 +122,10 @@ export interface IModuleCard { const Variables = z .object({ - trusted_users: z.array(z.string()).optional().default([]), - trusted_groups: z.array(z.string()).optional().default([]), - owner_users: z.array(z.string()).optional().default([]), - owner_groups: z.array(z.string()).optional().default([]), + trusted_users: z.array(z.string()).optional(), + trusted_groups: z.array(z.string()).optional(), + owner_users: z.array(z.string()).optional(), + owner_groups: z.array(z.string()).optional(), }) .passthrough() export type IVariables = z.infer @@ -304,5 +304,16 @@ const emailOptions = z.object({ recipients: z.array(z.string()), subject: z.string(), mailBody: z.string(), + credentials: z.object({ + email: z.string(), + password: z.string(), + }), }) export type IEmailOptions = z.infer + +const secretManagerRequest = z.object({ + key: z.string(), + value: z.string(), +}) + +export type ISecretManagerReq = z.infer From 5286bf038626e122adfe0e09fc8e967165f94476 Mon Sep 17 00:00:00 2001 From: Sachin Date: Fri, 22 Sep 2023 14:53:46 +0000 Subject: [PATCH 04/16] Description of email notification check box updated --- radlab-ui/webapp/src/utils/data.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radlab-ui/webapp/src/utils/data.ts b/radlab-ui/webapp/src/utils/data.ts index 6f7dc8b7..5af886d9 100644 --- a/radlab-ui/webapp/src/utils/data.ts +++ b/radlab-ui/webapp/src/utils/data.ts @@ -887,7 +887,7 @@ variable "folder_id" { } variable "email_notifications" { - description = "Email notifications toggle for enabling email notifications for users. {{UIMeta group=4 order=1 }}" + description = "Enable Email notifications to Trusted and Owner Users / Groups for RAD Lab module updates. {{UIMeta group=4 order=1 }}" type = bool default = false } From 4f3b044248dd11f5900eee1b377696ada48dfba5 Mon Sep 17 00:00:00 2001 From: SachinSogoduRaju <104055453+SachinSogoduRaju@users.noreply.github.com> Date: Tue, 26 Sep 2023 08:32:38 +0000 Subject: [PATCH 05/16] Update radlab-ui/webapp/src/components/forms/DefaultStepCreator.tsx Co-authored-by: Alan Colver <69013624+acolver@users.noreply.github.com> --- radlab-ui/webapp/src/components/forms/DefaultStepCreator.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/radlab-ui/webapp/src/components/forms/DefaultStepCreator.tsx b/radlab-ui/webapp/src/components/forms/DefaultStepCreator.tsx index b52692ae..1dbae34d 100644 --- a/radlab-ui/webapp/src/components/forms/DefaultStepCreator.tsx +++ b/radlab-ui/webapp/src/components/forms/DefaultStepCreator.tsx @@ -37,8 +37,6 @@ const DefaultStepCreator: React.FC = ({ const renderControls = (variable: IUIVariable) => { switch (variable.type) { - case "string": - return case "bool": return default: From 02fd98078f3ccc15a260250f1dbd92ff04b7a8d7 Mon Sep 17 00:00:00 2001 From: SachinSogoduRaju <104055453+SachinSogoduRaju@users.noreply.github.com> Date: Tue, 26 Sep 2023 09:02:18 +0000 Subject: [PATCH 06/16] Update radlab-ui/webapp/src/utils/mailHandler.ts Co-authored-by: Alan Colver <69013624+acolver@users.noreply.github.com> --- radlab-ui/webapp/src/utils/mailHandler.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/radlab-ui/webapp/src/utils/mailHandler.ts b/radlab-ui/webapp/src/utils/mailHandler.ts index 88b20745..be555f52 100644 --- a/radlab-ui/webapp/src/utils/mailHandler.ts +++ b/radlab-ui/webapp/src/utils/mailHandler.ts @@ -34,6 +34,7 @@ export const configureEmailAndSend = async ( //fetch mailbox password from secret manager const password = await getSecretKeyValue("mailBoxCred") if (!password) { + console.error("No email password found") return } From d22a83d03e23107ed6eb8cbf4537a03af36ad971 Mon Sep 17 00:00:00 2001 From: SachinSogoduRaju <104055453+SachinSogoduRaju@users.noreply.github.com> Date: Tue, 26 Sep 2023 09:02:31 +0000 Subject: [PATCH 07/16] Update radlab-ui/webapp/src/utils/mailHandler.ts Co-authored-by: Alan Colver <69013624+acolver@users.noreply.github.com> --- radlab-ui/webapp/src/utils/mailHandler.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/radlab-ui/webapp/src/utils/mailHandler.ts b/radlab-ui/webapp/src/utils/mailHandler.ts index be555f52..a0ec785c 100644 --- a/radlab-ui/webapp/src/utils/mailHandler.ts +++ b/radlab-ui/webapp/src/utils/mailHandler.ts @@ -157,9 +157,7 @@ export const sendMail = async (emailOptions: IEmailOptions) => { return } - const uniqueRecipients = recipients.filter( - (item, index) => recipients.indexOf(item) === index, - ) + const uniqueRecipients = [...new Set(recipients)] let transporter = nodemailer.createTransport({ service: "gmail", From 9d0deba8755b22a30131f127e9a9882df4b8e990 Mon Sep 17 00:00:00 2001 From: Sachin Date: Tue, 26 Sep 2023 09:24:18 +0000 Subject: [PATCH 08/16] PR review Changes --- .../docs/rad-lab-ui/ui_installation/env-variables.md | 1 + radlab-ui/webapp/.env.development | 1 + radlab-ui/webapp/.env.production | 1 + .../src/components/forms/DefaultCreateForm.tsx | 12 ++++++------ radlab-ui/webapp/src/pages/api/secret.ts | 7 ++++++- radlab-ui/webapp/src/utils/data.ts | 10 +++++----- radlab-ui/webapp/src/utils/mailHandler.ts | 4 ++-- 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/docs/docs/rad-lab-ui/ui_installation/env-variables.md b/docs/docs/rad-lab-ui/ui_installation/env-variables.md index 031ca13c..6339bc73 100644 --- a/docs/docs/rad-lab-ui/ui_installation/env-variables.md +++ b/docs/docs/rad-lab-ui/ui_installation/env-variables.md @@ -35,6 +35,7 @@ Firebase environment variables can be found in project settings section of your - `NEXT_PUBLIC_NOTIFICATION_TOPIC` - Topic created for notifications - `NEXT_PUBLIC_NOTIFICATION_SUB` - Subscription created for notifications - `NEXT_PUBLIC_GIT_API_URL` - Url of the public repo to pull the deployment modules +- `SECRET_MANAGER_LOCATION` - Location of the Google secret manager to store the secrets(replica set) ## Git Hub repo envs diff --git a/radlab-ui/webapp/.env.development b/radlab-ui/webapp/.env.development index abc0a4a1..374381c2 100644 --- a/radlab-ui/webapp/.env.development +++ b/radlab-ui/webapp/.env.development @@ -24,3 +24,4 @@ NEXT_PUBLIC_RAD_LAB_DOCS_SITE=https://googlecloudplatform.github.io/rad-lab/ MODULE_DEPLOYMENT_BUCKET_NAME= GIT_TOKEN_SECRET_KEY_NAME=rad-lab-git-access-token +SECRET_MANAGER_LOCATION= diff --git a/radlab-ui/webapp/.env.production b/radlab-ui/webapp/.env.production index 5525ae5d..dee45f69 100644 --- a/radlab-ui/webapp/.env.production +++ b/radlab-ui/webapp/.env.production @@ -24,4 +24,5 @@ NEXT_PUBLIC_RAD_LAB_DOCS_SITE=https://googlecloudplatform.github.io/rad-lab/ MODULE_DEPLOYMENT_BUCKET_NAME= GIT_TOKEN_SECRET_KEY_NAME=rad-lab-git-access-token +SECRET_MANAGER_LOCATION= diff --git a/radlab-ui/webapp/src/components/forms/DefaultCreateForm.tsx b/radlab-ui/webapp/src/components/forms/DefaultCreateForm.tsx index 9995d493..cd4888f9 100644 --- a/radlab-ui/webapp/src/components/forms/DefaultCreateForm.tsx +++ b/radlab-ui/webapp/src/components/forms/DefaultCreateForm.tsx @@ -44,12 +44,12 @@ const DefaultCreateForm: React.FC = ({ if (values.email_notifications) { const secretManagerPayload: ISecretManagerReq = { key: "mailBoxCred", - value: values.mail_box_password, + value: values.mail_server_password, } await saveMailBoxCred(secretManagerPayload) } - delete values.mail_box_password + delete values.mail_server_password const payload = Object.assign(values, { email: user?.email, }) @@ -109,13 +109,13 @@ const DefaultCreateForm: React.FC = ({ ) => { const allNonDependsVars = formVariablesData.filter( (formVariableData) => - formVariableData.name !== "mail_box_email" && - formVariableData.name !== "mail_box_password", + formVariableData.name !== "mail_server_email" && + formVariableData.name !== "mail_server_password", ) const allDependsVars = formVariablesData.filter( (formVariableData) => - formVariableData.name === "mail_box_email" || - formVariableData.name === "mail_box_password", + formVariableData.name === "mail_server_email" || + formVariableData.name === "mail_server_password", ) const notificationAnswer = currentAnswerValueData.email_notifications diff --git a/radlab-ui/webapp/src/pages/api/secret.ts b/radlab-ui/webapp/src/pages/api/secret.ts index bb59d51d..b02bd023 100644 --- a/radlab-ui/webapp/src/pages/api/secret.ts +++ b/radlab-ui/webapp/src/pages/api/secret.ts @@ -10,6 +10,11 @@ const gcpProjectId = envOrFail( process.env.NEXT_PUBLIC_GCP_PROJECT_ID, ) +const secretManagerLocation = envOrFail( + "SECRET_MANAGER_LOCATION", + process.env.SECRET_MANAGER_LOCATION, +) + export const getSecretKeyValue = async (secretId: string) => { try { const parent = `projects/${gcpProjectId}` @@ -39,7 +44,7 @@ const createSecret = async (req: NextApiRequest, res: NextApiResponse) => { userManaged: { replicas: [ { - location: "us-central1", + location: secretManagerLocation, }, ], }, diff --git a/radlab-ui/webapp/src/utils/data.ts b/radlab-ui/webapp/src/utils/data.ts index 5af886d9..2cb3fdc9 100644 --- a/radlab-ui/webapp/src/utils/data.ts +++ b/radlab-ui/webapp/src/utils/data.ts @@ -887,17 +887,17 @@ variable "folder_id" { } variable "email_notifications" { - description = "Enable Email notifications to Trusted and Owner Users / Groups for RAD Lab module updates. {{UIMeta group=4 order=1 }}" + description = "Enable/Disable Email notifications to Trusted and Owner Users / Groups for RAD Lab module updates. {{UIMeta group=4 order=1 }}" type = bool default = false } -variable "mail_box_email" { - description = "Mail Box Email Id. {{UIMeta group=4 order=2 }}" +variable "mail_server_email" { + description = "Mail Server Email Id for sending email notifications. {{UIMeta group=4 order=2 }}" type = string default = "" } -variable "mail_box_password" { - description = "Mail Box Password. {{UIMeta group=4 order=3 }}" +variable "mail_server_password" { + description = "Mail Server Password to authenticate your mail server(Password will be stored in Google Secret Manager). {{UIMeta group=4 order=3 }}" type = string default = "" } diff --git a/radlab-ui/webapp/src/utils/mailHandler.ts b/radlab-ui/webapp/src/utils/mailHandler.ts index a0ec785c..52368e55 100644 --- a/radlab-ui/webapp/src/utils/mailHandler.ts +++ b/radlab-ui/webapp/src/utils/mailHandler.ts @@ -81,7 +81,7 @@ export const configureEmailAndSend = async ( subject: mailSubject, mailBody: htmlToSend, credentials: { - email: settings.variables.mail_box_email, + email: settings.variables.mail_server_email, password, }, } @@ -142,7 +142,7 @@ export const configureEmailAndSend = async ( subject: mailSubject, mailBody: htmlToSend, credentials: { - email: settings.variables.mail_box_email, + email: settings.variables.mail_server_email, password, }, } From b9a5dc928c003372cbd317e4111db0ef4322b1a6 Mon Sep 17 00:00:00 2001 From: SachinSogoduRaju <104055453+SachinSogoduRaju@users.noreply.github.com> Date: Tue, 26 Sep 2023 15:50:03 +0000 Subject: [PATCH 09/16] Update radlab-ui/webapp/src/utils/mailHandler.ts Co-authored-by: Alan Colver <69013624+acolver@users.noreply.github.com> --- radlab-ui/webapp/src/utils/mailHandler.ts | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/radlab-ui/webapp/src/utils/mailHandler.ts b/radlab-ui/webapp/src/utils/mailHandler.ts index 52368e55..186faafb 100644 --- a/radlab-ui/webapp/src/utils/mailHandler.ts +++ b/radlab-ui/webapp/src/utils/mailHandler.ts @@ -175,11 +175,8 @@ export const sendMail = async (emailOptions: IEmailOptions) => { subject: emailOptions.subject, html: emailOptions.mailBody, } - transporter + return transporter .sendMail(mailConfiguration) - .then((res) => { - console.log("Mail sent", res) - }) .catch((error) => { console.error("Error", error) }) From e500a5114aeebaaaa51878472492b8288b21af20 Mon Sep 17 00:00:00 2001 From: SachinSogoduRaju <104055453+SachinSogoduRaju@users.noreply.github.com> Date: Tue, 26 Sep 2023 15:50:13 +0000 Subject: [PATCH 10/16] Update docs/docs/rad-lab-ui/ui_installation/env-variables.md Co-authored-by: Alan Colver <69013624+acolver@users.noreply.github.com> --- docs/docs/rad-lab-ui/ui_installation/env-variables.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/rad-lab-ui/ui_installation/env-variables.md b/docs/docs/rad-lab-ui/ui_installation/env-variables.md index 6339bc73..6ebc0a6f 100644 --- a/docs/docs/rad-lab-ui/ui_installation/env-variables.md +++ b/docs/docs/rad-lab-ui/ui_installation/env-variables.md @@ -35,7 +35,7 @@ Firebase environment variables can be found in project settings section of your - `NEXT_PUBLIC_NOTIFICATION_TOPIC` - Topic created for notifications - `NEXT_PUBLIC_NOTIFICATION_SUB` - Subscription created for notifications - `NEXT_PUBLIC_GIT_API_URL` - Url of the public repo to pull the deployment modules -- `SECRET_MANAGER_LOCATION` - Location of the Google secret manager to store the secrets(replica set) +- `SECRET_MANAGER_LOCATION` - Google Cloud region of the Secret Manager instance ## Git Hub repo envs From fa42080892d38a90a2dfdf9baeede473b55c9ad4 Mon Sep 17 00:00:00 2001 From: Sachin Date: Tue, 26 Sep 2023 15:56:16 +0000 Subject: [PATCH 11/16] updated mailhandler function --- docs/docs/rad-lab-ui/troubleshooting.md | 6 ++++++ radlab-ui/webapp/src/utils/mailHandler.ts | 10 ++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/docs/rad-lab-ui/troubleshooting.md b/docs/docs/rad-lab-ui/troubleshooting.md index 7ee5ef58..d336c01c 100644 --- a/docs/docs/rad-lab-ui/troubleshooting.md +++ b/docs/docs/rad-lab-ui/troubleshooting.md @@ -3,4 +3,10 @@ sidebar_position: 4 --- # Troubleshooting +### Email Server setup +Email notifications are customizable,Admins can `enable` or `disable` email notifications on `Global Variables` setup. +Inorder to proceed with email notifications admin has to store the email server (smtp server or a dedicated e-mail) credentials as part of `Global Variables`. + +`MAIL SERVER EMAIL` will be stored in `firestore` and `MAIL SERVER PASSWORD` will be securly stored on `Google Secret Manager` + Please feel free to reach out and to create a [GitHub issue](https://github.com/GoogleCloudPlatform/rad-lab/issues) in case of any issues or concerns. diff --git a/radlab-ui/webapp/src/utils/mailHandler.ts b/radlab-ui/webapp/src/utils/mailHandler.ts index 186faafb..83e99927 100644 --- a/radlab-ui/webapp/src/utils/mailHandler.ts +++ b/radlab-ui/webapp/src/utils/mailHandler.ts @@ -167,7 +167,7 @@ export const sendMail = async (emailOptions: IEmailOptions) => { }, }) - transporter.verify().then(console.log).catch(console.error) + await transporter.verify().catch(console.error) const mailConfiguration = { from: credentials.email, @@ -175,9 +175,7 @@ export const sendMail = async (emailOptions: IEmailOptions) => { subject: emailOptions.subject, html: emailOptions.mailBody, } - return transporter - .sendMail(mailConfiguration) - .catch((error) => { - console.error("Error", error) - }) + return transporter.sendMail(mailConfiguration).catch((error) => { + console.error("Error", error) + }) } From 1d1fb57b8fb9e576a6e4f7fbff38da7ebe6d56aa Mon Sep 17 00:00:00 2001 From: SachinSogoduRaju <104055453+SachinSogoduRaju@users.noreply.github.com> Date: Tue, 26 Sep 2023 16:39:18 +0000 Subject: [PATCH 12/16] Update docs/docs/rad-lab-ui/troubleshooting.md Co-authored-by: Alan Colver <69013624+acolver@users.noreply.github.com> --- docs/docs/rad-lab-ui/troubleshooting.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/docs/docs/rad-lab-ui/troubleshooting.md b/docs/docs/rad-lab-ui/troubleshooting.md index d336c01c..c2be1851 100644 --- a/docs/docs/rad-lab-ui/troubleshooting.md +++ b/docs/docs/rad-lab-ui/troubleshooting.md @@ -3,10 +3,19 @@ sidebar_position: 4 --- # Troubleshooting -### Email Server setup -Email notifications are customizable,Admins can `enable` or `disable` email notifications on `Global Variables` setup. -Inorder to proceed with email notifications admin has to store the email server (smtp server or a dedicated e-mail) credentials as part of `Global Variables`. +Please feel free to reach out and to create a [GitHub issue](https://github.com/GoogleCloudPlatform/rad-lab/issues) in case of any issues or concerns. -`MAIL SERVER EMAIL` will be stored in `firestore` and `MAIL SERVER PASSWORD` will be securly stored on `Google Secret Manager` +## Email Notifications +You can optionally enable RAD Lab notification for deployment events. This includes deployment creations, updates, and deletions. + +If enabled, the following users/groups (defined in the module's Terraform variables) will receive email notifications: +- The individual taking the action +- `trusted_users` +- `trusted_groups` +- `owner_users` +- `owner_groups` + +Currently only sending via gmail is supported. It is recommended to [create a new gmail address](https://support.google.com/mail/answer/56256?hl=en) for this purpose only. Do **not** enable two factor authentication (2FA) on this account. You will then provide this email and its password to RAD Lab UI via the `Global Variables` setup. + +The email address will be store in Firestore, and email password will be securely stored in Google's [Secret Manager](https://cloud.google.com/secret-manager) -Please feel free to reach out and to create a [GitHub issue](https://github.com/GoogleCloudPlatform/rad-lab/issues) in case of any issues or concerns. From fc5579d75661f349ea4419913fc83f3ba3795d06 Mon Sep 17 00:00:00 2001 From: Alan Colver Date: Tue, 26 Sep 2023 15:25:22 -0600 Subject: [PATCH 13/16] Add fallback value to SECRET_MANAGER_LOCATION. Update some variable descriptions --- radlab-ui/webapp/src/pages/api/secret.ts | 1 + radlab-ui/webapp/src/utils/data.ts | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/radlab-ui/webapp/src/pages/api/secret.ts b/radlab-ui/webapp/src/pages/api/secret.ts index b02bd023..38677603 100644 --- a/radlab-ui/webapp/src/pages/api/secret.ts +++ b/radlab-ui/webapp/src/pages/api/secret.ts @@ -13,6 +13,7 @@ const gcpProjectId = envOrFail( const secretManagerLocation = envOrFail( "SECRET_MANAGER_LOCATION", process.env.SECRET_MANAGER_LOCATION, + "us-central1", ) export const getSecretKeyValue = async (secretId: string) => { diff --git a/radlab-ui/webapp/src/utils/data.ts b/radlab-ui/webapp/src/utils/data.ts index 2cb3fdc9..8ccb8c44 100644 --- a/radlab-ui/webapp/src/utils/data.ts +++ b/radlab-ui/webapp/src/utils/data.ts @@ -887,17 +887,17 @@ variable "folder_id" { } variable "email_notifications" { - description = "Enable/Disable Email notifications to Trusted and Owner Users / Groups for RAD Lab module updates. {{UIMeta group=4 order=1 }}" + description = "Enable email notifications to Trusted and Owner Users/Groups for RAD Lab deployment events. {{UIMeta group=4 order=1 }}" type = bool default = false } variable "mail_server_email" { - description = "Mail Server Email Id for sending email notifications. {{UIMeta group=4 order=2 }}" + description = "Gmail address for sending email notifications. {{UIMeta group=4 order=2 }}" type = string default = "" } variable "mail_server_password" { - description = "Mail Server Password to authenticate your mail server(Password will be stored in Google Secret Manager). {{UIMeta group=4 order=3 }}" + description = "Gmail password (see more at https://googlecloudplatform.github.io/rad-lab/docs/rad-lab-ui/troubleshooting). {{UIMeta group=4 order=3 }}" type = string default = "" } From d1768195c60d5ec20258a664850cc729d4ff9c60 Mon Sep 17 00:00:00 2001 From: Sachin Date: Wed, 27 Sep 2023 14:37:35 +0000 Subject: [PATCH 14/16] updated troubleshooting doc --- docs/docs/rad-lab-ui/troubleshooting.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/docs/rad-lab-ui/troubleshooting.md b/docs/docs/rad-lab-ui/troubleshooting.md index c2be1851..b1bb50f9 100644 --- a/docs/docs/rad-lab-ui/troubleshooting.md +++ b/docs/docs/rad-lab-ui/troubleshooting.md @@ -15,7 +15,9 @@ If enabled, the following users/groups (defined in the module's Terraform variab - `owner_users` - `owner_groups` -Currently only sending via gmail is supported. It is recommended to [create a new gmail address](https://support.google.com/mail/answer/56256?hl=en) for this purpose only. Do **not** enable two factor authentication (2FA) on this account. You will then provide this email and its password to RAD Lab UI via the `Global Variables` setup. +Currently only sending via gmail is supported. It is recommended to [create a new gmail address](https://support.google.com/mail/answer/56256?hl=en) for this purpose only and generate a `App Password` to authenticate it by followig [Sign in with app passwords](https://support.google.com/mail/answer/185833?hl=en) + + You will then provide this email and its password to RAD Lab UI via the `Global Variables` setup. The email address will be store in Firestore, and email password will be securely stored in Google's [Secret Manager](https://cloud.google.com/secret-manager) From bf43e99bc6f690f5c82825f0a7dbca410c81f985 Mon Sep 17 00:00:00 2001 From: Alan Colver <69013624+acolver@users.noreply.github.com> Date: Wed, 27 Sep 2023 09:34:53 -0600 Subject: [PATCH 15/16] Update docs/docs/rad-lab-ui/troubleshooting.md --- docs/docs/rad-lab-ui/troubleshooting.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/rad-lab-ui/troubleshooting.md b/docs/docs/rad-lab-ui/troubleshooting.md index b1bb50f9..f90eb203 100644 --- a/docs/docs/rad-lab-ui/troubleshooting.md +++ b/docs/docs/rad-lab-ui/troubleshooting.md @@ -15,7 +15,7 @@ If enabled, the following users/groups (defined in the module's Terraform variab - `owner_users` - `owner_groups` -Currently only sending via gmail is supported. It is recommended to [create a new gmail address](https://support.google.com/mail/answer/56256?hl=en) for this purpose only and generate a `App Password` to authenticate it by followig [Sign in with app passwords](https://support.google.com/mail/answer/185833?hl=en) +Currently only sending via gmail is supported. It is recommended to [create a new gmail address](https://support.google.com/mail/answer/56256?hl=en) for this purpose only and generate an `App Password` to authenticate it by following [these directions](https://support.google.com/mail/answer/185833?hl=en). You will then provide this email and its password to RAD Lab UI via the `Global Variables` setup. From 3e8ea663604a41892955d1cb7b923aea4d5e4e92 Mon Sep 17 00:00:00 2001 From: Sachin Date: Fri, 29 Sep 2023 14:00:53 +0000 Subject: [PATCH 16/16] Update docs fro email notifications and env moved to terraform output --- docs/docs/rad-lab-ui/troubleshooting.md | 16 ---------------- .../ui_installation/publishing-modules.md | 19 ++++++++++++++++++- .../terraform/infrastructure/outputs.tf | 4 ++++ .../terraform/infrastructure/variables.tf | 6 ++++++ radlab-ui/webapp/gen_local_config.sh | 2 ++ 5 files changed, 30 insertions(+), 17 deletions(-) diff --git a/docs/docs/rad-lab-ui/troubleshooting.md b/docs/docs/rad-lab-ui/troubleshooting.md index f90eb203..e59807f6 100644 --- a/docs/docs/rad-lab-ui/troubleshooting.md +++ b/docs/docs/rad-lab-ui/troubleshooting.md @@ -5,19 +5,3 @@ sidebar_position: 4 Please feel free to reach out and to create a [GitHub issue](https://github.com/GoogleCloudPlatform/rad-lab/issues) in case of any issues or concerns. -## Email Notifications -You can optionally enable RAD Lab notification for deployment events. This includes deployment creations, updates, and deletions. - -If enabled, the following users/groups (defined in the module's Terraform variables) will receive email notifications: -- The individual taking the action -- `trusted_users` -- `trusted_groups` -- `owner_users` -- `owner_groups` - -Currently only sending via gmail is supported. It is recommended to [create a new gmail address](https://support.google.com/mail/answer/56256?hl=en) for this purpose only and generate an `App Password` to authenticate it by following [these directions](https://support.google.com/mail/answer/185833?hl=en). - - You will then provide this email and its password to RAD Lab UI via the `Global Variables` setup. - -The email address will be store in Firestore, and email password will be securely stored in Google's [Secret Manager](https://cloud.google.com/secret-manager) - diff --git a/docs/docs/rad-lab-ui/ui_installation/publishing-modules.md b/docs/docs/rad-lab-ui/ui_installation/publishing-modules.md index b80fc12b..944a5198 100644 --- a/docs/docs/rad-lab-ui/ui_installation/publishing-modules.md +++ b/docs/docs/rad-lab-ui/ui_installation/publishing-modules.md @@ -16,7 +16,23 @@ Some variables are common to all modules. Upon first log in, and Admin will set - Billing ID - Organization ID (without `organizations/`-prefix) - Folder ID (without `folders/`-prefix) -- Preferred Google Cloud Region and Zone +- Email Notification(enable/disable email notifications) + +#### Email Notifications +You can optionally enable RAD Lab notification for deployment events. This includes deployment creations, updates, and deletions. + +If enabled, the following users/groups (defined in the module's Terraform variables) will receive email notifications: +- The individual taking the action +- `trusted_users` +- `trusted_groups` +- `owner_users` +- `owner_groups` + +Currently only sending via gmail is supported. It is recommended to [create a new gmail address](https://support.google.com/mail/answer/56256?hl=en) for this purpose only and generate an `App Password` to authenticate it by following [these directions](https://support.google.com/mail/answer/185833?hl=en). + + You will then provide this email and its password to RAD Lab UI via the `Global Variables` setup. + +The email address will be store in Firestore, and email password will be securely stored in Google's [Secret Manager](https://cloud.google.com/secret-manager) ## Module Admin Variables @@ -25,3 +41,4 @@ Lastly, some modules have specific requirements for variables that typical Users Once an Admin tries to publish a module, if the module requires any of these variables, the Admin will be prompted. These values will be saved in Firestore and inaccessible to Users. When a User deploys a module, Global and Module Admin Variables will be combined with the variables the User provided and passed to Terraform for execution (User variables supersede all other variables of the same name, and Module Admin variable supersede Global Admin variables of the same name). + diff --git a/radlab-ui/automation/terraform/infrastructure/outputs.tf b/radlab-ui/automation/terraform/infrastructure/outputs.tf index 9680c814..6da30f88 100644 --- a/radlab-ui/automation/terraform/infrastructure/outputs.tf +++ b/radlab-ui/automation/terraform/infrastructure/outputs.tf @@ -18,6 +18,10 @@ output "admin_group_name" { value = var.admin_group_name } +output "secret_manager_location" { + value = var.secret_manager_location +} + output "app_engine_url" { value = google_app_engine_application.radlab_ui.default_hostname } diff --git a/radlab-ui/automation/terraform/infrastructure/variables.tf b/radlab-ui/automation/terraform/infrastructure/variables.tf index 22b777e8..24f63262 100644 --- a/radlab-ui/automation/terraform/infrastructure/variables.tf +++ b/radlab-ui/automation/terraform/infrastructure/variables.tf @@ -20,6 +20,12 @@ variable "admin_group_name" { default = "rad-lab-admins" } +variable "secret_manager_location" { + description = "The location where the secret is stored in the Secret Manager." + type = string + default = "us-central1" +} + variable "app_engine_location" { description = "The location where the App Engine project will be created." type = string diff --git a/radlab-ui/webapp/gen_local_config.sh b/radlab-ui/webapp/gen_local_config.sh index cec37fc4..6d0665f6 100755 --- a/radlab-ui/webapp/gen_local_config.sh +++ b/radlab-ui/webapp/gen_local_config.sh @@ -39,6 +39,7 @@ MODULE_DEPLOYMENT_BUCKET_NAME=$(echo "${TERRAFORM_OUTPUT}" | jq -r .values.outpu GITHUB_URL=$(echo "${TERRAFORM_OUTPUT}" | jq -r .values.outputs.git_repo_url.value) GITHUB_BRANCH=$(echo "${TERRAFORM_OUTPUT}" | jq -r .values.outputs.git_repo_branch.value) GIT_TOKEN_SECRET_KEY_NAME=$(echo "${TERRAFORM_OUTPUT}" | jq -r .values.outputs.git_personal_access_token_secret_id.value) +SECRET_MANAGER_LOCATION=$(echo "${TERRAFORM_OUTPUT}" | jq -r .values.outputs.secret_manager_location.value) cd $WEBAPP_DIR FIREBASE_CONFIG_OUTPUT=$(firebase apps:sdkconfig web --project ${PROJECT_ID} --json) @@ -90,5 +91,6 @@ NEXT_PUBLIC_RAD_LAB_USER_GROUP=${USER_GROUP_NAME} MODULE_DEPLOYMENT_BUCKET_NAME=${MODULE_DEPLOYMENT_BUCKET_NAME} GIT_TOKEN_SECRET_KEY_NAME=${GIT_TOKEN_SECRET_KEY_NAME} +SECRET_MANAGER_LOCATION=${SECRET_MANAGER_LOCATION} EOT done