Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

release(v0.25.0): merge to prod #750

Merged
merged 10 commits into from
May 4, 2023
21 changes: 17 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,22 @@ All notable changes to this project will be documented in this file. Dates are d

Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

#### [v0.25.0](https://github.com/isomerpages/isomercms-backend/compare/v0.24.2...v0.25.0)

- fix(markdown-utils): add check for falsy values [`#746`](https://github.com/isomerpages/isomercms-backend/pull/746)
- chore: add logging to endpoints being called [`#744`](https://github.com/isomerpages/isomercms-backend/pull/744)
- feat(datadog): add tracing for http requests out [`#745`](https://github.com/isomerpages/isomercms-backend/pull/745)
- feat(site creation): add support for email + github logins [`#739`](https://github.com/isomerpages/isomercms-backend/pull/739)
- Hotfix/0.24.2 [`#743`](https://github.com/isomerpages/isomercms-backend/pull/743)
- Fix: add svg to allowed image types [`#738`](https://github.com/isomerpages/isomercms-backend/pull/738)
- fix(site launch email): make table nicer [`#732`](https://github.com/isomerpages/isomercms-backend/pull/732)
- hotfix/0.24.1 [`#737`](https://github.com/isomerpages/isomercms-backend/pull/737)
- 0.24.0 [`#735`](https://github.com/isomerpages/isomercms-backend/pull/735)

#### [v0.24.2](https://github.com/isomerpages/isomercms-backend/compare/v0.24.1...v0.24.2)

> 3 May 2023

- fix: token capacity alarm message ordering [`43ac12b`](https://github.com/isomerpages/isomercms-backend/commit/43ac12bab0114f7563428ce90cc9f55584a43422)

#### [v0.24.1](https://github.com/isomerpages/isomercms-backend/compare/v0.23.1...v0.24.1)
Expand Down Expand Up @@ -86,12 +100,12 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
- build(deps): bump vm2 from 3.9.12 to 3.9.15 in /microservices [`#688`](https://github.com/isomerpages/isomercms-backend/pull/688)
- build(deps): bump vm2 from 3.9.11 to 3.9.15 [`#687`](https://github.com/isomerpages/isomercms-backend/pull/687)
- release(0.19.0): merge to develop [`#684`](https://github.com/isomerpages/isomercms-backend/pull/684)
- fix(utils): sanitize empty string + trim [`#686`](https://github.com/isomerpages/isomercms-backend/pull/686)

#### [v0.19.0](https://github.com/isomerpages/isomercms-backend/compare/v0.18.2...v0.19.0)

> 6 April 2023

- fix(utils): sanitize empty string + trim [`#686`](https://github.com/isomerpages/isomercms-backend/pull/686)
- fix(utils): change order of ops and rec sanitization [`#680`](https://github.com/isomerpages/isomercms-backend/pull/680)
- chore(review): fix tests for review router [`#683`](https://github.com/isomerpages/isomercms-backend/pull/683)
- Feat(site launch): support for multiple sites [`#665`](https://github.com/isomerpages/isomercms-backend/pull/665)
Expand All @@ -103,15 +117,14 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).

> 3 April 2023

- fix(review): return 200 for unmigrated sites [`bd69c29`](https://github.com/isomerpages/isomercms-backend/commit/bd69c29023554c5dcf8cb361227ba4ebf0d1ac08)
- fix(sanitize): use same setup for dompurify as FE [`c25f448`](https://github.com/isomerpages/isomercms-backend/commit/c25f448813e1addce67d0209375ec35ef9cb6c7b)
- Fix: change response for github users accessing collaborator endpoints [`db1130f`](https://github.com/isomerpages/isomercms-backend/commit/db1130f96a6c9cda99df43d5774134aefffeee3e)

#### [v0.18.1](https://github.com/isomerpages/isomercms-backend/compare/v0.18.0...v0.18.1)

> 31 March 2023

- fix(review): return 200 for unmigrated sites [`073cab8`](https://github.com/isomerpages/isomercms-backend/commit/073cab8c6704178ee5061b8582b4f999720dfc95)
- fix(review): return 200 for unmigrated sites [`bd69c29`](https://github.com/isomerpages/isomercms-backend/commit/bd69c29023554c5dcf8cb361227ba4ebf0d1ac08)
- fix(sanitize): use same setup for dompurify as FE [`c25f448`](https://github.com/isomerpages/isomercms-backend/commit/c25f448813e1addce67d0209375ec35ef9cb6c7b)

#### [v0.18.0](https://github.com/isomerpages/isomercms-backend/compare/v0.17.0...v0.18.0)

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "isomercms",
"version": "0.24.2",
"version": "0.25.0",
"private": true,
"scripts": {
"build": "tsc -p tsconfig.build.json",
Expand Down
21 changes: 12 additions & 9 deletions src/routes/formsgSiteCreation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { config } from "@config/config"
import logger from "@logger/logger"

import { BadRequestError } from "@errors/BadRequestError"
import InitializationError from "@errors/InitializationError"

import { getField } from "@utils/formsg-utils"

Expand All @@ -21,6 +20,7 @@ const REQUESTER_EMAIL_FIELD = "Government E-mail"
const SITE_NAME_FIELD = "Site Name"
const REPO_NAME_FIELD = "Repository Name"
const OWNER_NAME_FIELD = "Site Owner E-mail"
const LOGIN_TYPE_FIELD = "Login Type"

export interface FormsgRouterProps {
usersService: UsersService
Expand Down Expand Up @@ -55,7 +55,7 @@ export class FormsgRouter {
const ownerEmail = getField(responses, OWNER_NAME_FIELD)
?.toLowerCase()
.trim()

const isEmailLogin = getField(responses, LOGIN_TYPE_FIELD) === "Email based"
logger.info(
`Create site form submission [${submissionId}] (repoName '${repoName}', siteName '${siteName}') requested by <${requesterEmail}>`
)
Expand Down Expand Up @@ -87,15 +87,18 @@ export class FormsgRouter {
await this.sendCreateError(requesterEmail, repoName, submissionId, err)
return res.sendStatus(200)
}
const foundOwner = await this.usersService.findOrCreateByEmail(ownerEmail)

let foundOwner
if (isEmailLogin) {
foundOwner = await this.usersService.findOrCreateByEmail(ownerEmail)
}
// 3. Use service to create site
const { deployment } = await this.infraService.createSite(
foundIsomerRequester,
foundOwner,
const { deployment } = await this.infraService.createSite({
creator: foundIsomerRequester,
member: foundOwner,
siteName,
repoName
)
repoName,
isEmailLogin,
})
await this.sendCreateSuccess(
requesterEmail,
repoName,
Expand Down
93 changes: 8 additions & 85 deletions src/routes/formsgSiteLaunch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ import { getField, getFieldsFromTable } from "@utils/formsg-utils"

import { attachFormSGHandler } from "@root/middleware"
import { mailer } from "@root/services/utilServices/MailClient"
import {
DnsRecordsEmailProps,
LaunchFailureEmailProps,
getDNSRecordsEmailBody,
getErrorEmailBody,
} from "@root/services/utilServices/SendDNSRecordEmailClient"
import UsersService from "@services/identity/UsersService"
import InfraService from "@services/infra/InfraService"

Expand Down Expand Up @@ -52,26 +58,6 @@ interface FormResponsesProps {
siteLaunchDetails?: string[] | string[][]
}

interface LaunchFailureEmailProps {
// The fields here are optional since a misconfiguration in our
// formSG can cause some or even all fields to be missing
requesterEmail?: string
repoName?: string
primaryDomain?: string
error: string
}

interface DnsRecordsEmailProps {
requesterEmail: string
repoName: string
domainValidationSource: string
domainValidationTarget: string
primaryDomainSource: string
primaryDomainTarget: string
redirectionDomainSource?: string
redirectionDomainTarget?: string
}

export class FormsgSiteLaunchRouter {
launchSiteFromForm = async (formResponses: FormResponsesProps) => {
const {
Expand Down Expand Up @@ -219,21 +205,7 @@ export class FormsgSiteLaunchRouter {
const { requesterEmail } = failureResults[0]
const email = requesterEmail || ISOMER_ADMIN_EMAIL
const subject = `[Isomer] Launch site FAILURE`
let html = `<p>The following sites were NOT launched successfully. (Form submission id [${submissionId}])</p>
<table><thread><tr><th>Repo Name</th><th>Error</th></tr></thread><tbody>`

failureResults.forEach((failureResult) => {
const displayedRepoName = failureResult.repoName || "<missing repo name>"
html += `
<tr>
<td>${displayedRepoName}</td>
<td>${failureResult.error}</td>
</tr>`
})
html += `
</tbody></table>
<p>This email was sent from the Isomer CMS backend.</p>`

const html = getErrorEmailBody(submissionId, failureResults)
await mailer.sendMail(email, subject, html)
}

Expand All @@ -244,56 +216,7 @@ export class FormsgSiteLaunchRouter {
if (dnsRecordsEmailProps.length === 0) return
const { requesterEmail } = dnsRecordsEmailProps[0]
const subject = `[Isomer] DNS records for launching websites`

let html = `<p>Isomer sites are in the process of launching. (Form submission id [${submissionId}])</p>
<table>
<thead>
<tr>
<th>Repo Name</th>
<th>Source</th>
<th>Target</th>
<th>Type</th>
</tr>
</thead>
<tbody>`
dnsRecordsEmailProps.forEach((dnsRecords) => {
// check if dnsRecords.redirectionDomain is undefined
const hasRedirection = !!dnsRecords.redirectionDomainSource
html += `
<tr>
<td>${dnsRecords.repoName}</td>
<td>${dnsRecords.domainValidationSource}</td>
<td>${dnsRecords.domainValidationTarget}</td>
<td>CNAME</td>
</tr>
<tr>
<td>${dnsRecords.repoName}</td>
<td>${
hasRedirection
? // if redirection, website will be hosted in the 'www' subdomain
`www.${dnsRecords.primaryDomainSource}`
: dnsRecords.primaryDomainSource
}</td>
<td>${dnsRecords.primaryDomainTarget}</td>
<td>CNAME</td>
</tr>`

if (hasRedirection) {
html += `
<tr>
<td>${dnsRecords.repoName}</td>
<td>${
// note that the source here is the primary domain source
// since the non-www will be the one pointing to our redirection server
dnsRecords.primaryDomainSource
}</td>
<td>${dnsRecords.redirectionDomainTarget}</td>
<td>A Record</td>
</tr>`
}
})
html += `</tbody></table>
<p>This email was sent from the Isomer CMS backend.</p>`
const html = getDNSRecordsEmailBody(submissionId, dnsRecordsEmailProps)
await mailer.sendMail(requesterEmail, subject, html)
}

Expand Down
3 changes: 2 additions & 1 deletion src/server.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "dd-trace/init"
// NOTE: the import for tracer doesn't resolve with path aliasing
import "./utils/tracer"
import "module-alias/register"
import SequelizeStoreFactory from "connect-session-sequelize"
import session from "express-session"
Expand Down
25 changes: 23 additions & 2 deletions src/services/api/AxiosInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { config } from "@config/config"
import logger from "@logger/logger"

import { getAccessToken } from "@utils/token-retrieval-utils"
import tracer from "@utils/tracer"

// Env vars
const GITHUB_ORG_NAME = config.get("github.orgName")
Expand All @@ -15,13 +16,33 @@ const requestFormatter = async (config: AxiosRequestConfig) => {
const authMessage = config.headers.Authorization

// If accessToken is missing, authMessage is `token `
if (
// NOTE: This also implies that the user has not provided
// their own github token and hence, are email login users.
const isEmailLoginUser =
!authMessage ||
authMessage === "token " ||
authMessage === "token undefined"
) {

if (isEmailLoginUser) {
const accessToken = await getAccessToken()
config.headers.Authorization = `token ${accessToken}`
tracer.use("http", {
hooks: {
request: (span, req, res) => {
span?.setTag("user.type", "email")
},
},
})
logger.info(`Email login user made call to Github API: ${config.url}`)
} else {
tracer.use("http", {
hooks: {
request: (span, req, res) => {
span?.setTag("user.type", "github")
},
},
})
logger.info(`Github login user made call to Github API: ${config.url}`)
}
return {
...config,
Expand Down
28 changes: 27 additions & 1 deletion src/services/identity/ReposService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,18 @@ export default class ReposService {
setupGithubRepo = async ({
repoName,
site,
isEmailLogin,
}: {
repoName: string
site: Site
isEmailLogin: boolean
}): Promise<Repo> => {
const repoUrl = `https://github.com/isomerpages/${repoName}`

await this.createRepoOnGithub(repoName)
if (!isEmailLogin) {
await this.createTeamOnGitHub(repoName)
}
await this.generateRepoAndPublishToGitHub(repoName, repoUrl)
return this.create({
name: repoName,
Expand All @@ -73,6 +78,15 @@ export default class ReposService {
})
}

createTeamOnGitHub = (
repoName: string
): Promise<octokitCreateTeamResponseType> =>
octokit.teams.create({
org: ISOMER_GITHUB_ORGANIZATION_NAME,
name: repoName,
privacy: "closed",
})

modifyDeploymentUrlsOnRepo = async (
repoName: string,
productionUrl: string,
Expand Down Expand Up @@ -147,7 +161,10 @@ export default class ReposService {
private: false,
})

setRepoAndTeamPermissions = async (repoName: string): Promise<void> => {
setRepoAndTeamPermissions = async (
repoName: string,
isEmailLogin: boolean
): Promise<void> => {
await octokit.repos.updateBranchProtection({
owner: ISOMER_GITHUB_ORGANIZATION_NAME,
repo: repoName,
Expand All @@ -170,6 +187,15 @@ export default class ReposService {
repo: repoName,
permission: "admin",
})
if (!isEmailLogin) {
await octokit.teams.addOrUpdateRepoPermissionsInOrg({
org: ISOMER_GITHUB_ORGANIZATION_NAME,
team_slug: repoName,
owner: ISOMER_GITHUB_ORGANIZATION_NAME,
repo: repoName,
permission: "push",
})
}
}

generateRepoAndPublishToGitHub = async (
Expand Down
Loading