Skip to content

Commit

Permalink
Feat/site creation form email (#679)
Browse files Browse the repository at this point in the history
* Feat: add findOrCreateByEmail

* Feat: add site member instead of github team

* Feat: update forms parsing

* Fix: update infraService initialisation

* Chore: remove unused createTeamOnGithub

* nit: update variable name

* chore: update todo with issue number

* Fix: trim user input
  • Loading branch information
alexanderleegs authored Apr 10, 2023
1 parent 4f8e50a commit d7e2788
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 25 deletions.
14 changes: 11 additions & 3 deletions src/routes/formsgSiteCreation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const SITE_CREATE_FORM_KEY = config.get("formSg.siteCreateFormKey")
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"

export interface FormsgRouterProps {
usersService: UsersService
Expand Down Expand Up @@ -51,6 +52,9 @@ export class FormsgRouter {
const requesterEmail = getField(responses, REQUESTER_EMAIL_FIELD)
const siteName = getField(responses, SITE_NAME_FIELD)
const repoName = getField(responses, REPO_NAME_FIELD)
const ownerEmail = getField(responses, OWNER_NAME_FIELD)
?.toLowerCase()
.trim()

logger.info(
`Create site form submission [${submissionId}] (repoName '${repoName}', siteName '${siteName}') requested by <${requesterEmail}>`
Expand All @@ -75,16 +79,20 @@ export class FormsgRouter {
await this.sendCreateError(requesterEmail, repoName, submissionId, err)
return res.sendStatus(200)
}
const foundUser = await this.usersService.findByEmail(requesterEmail)
if (!foundUser) {
const foundIsomerRequester = await this.usersService.findByEmail(
requesterEmail
)
if (!foundIsomerRequester) {
const err = `Form submitter ${requesterEmail} is not an Isomer user. Register an account for this user and try again.`
await this.sendCreateError(requesterEmail, repoName, submissionId, err)
return res.sendStatus(200)
}
const foundOwner = await this.usersService.findOrCreateByEmail(ownerEmail)

// 3. Use service to create site
const { deployment } = await this.infraService.createSite(
foundUser,
foundIsomerRequester,
foundOwner,
siteName,
repoName
)
Expand Down
21 changes: 11 additions & 10 deletions src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -159,16 +159,6 @@ const launchesService = new LaunchesService({
launchClient,
})
const queueService = new QueueService()
const infraService = new InfraService({
sitesService,
reposService,
deploymentsService,
launchesService,
queueService,
})

// poller for incoming queue
infraService.pollQueue()

const identityAuthService = getIdentityAuthService(gitHubService)
const collaboratorsService = new CollaboratorsService({
Expand All @@ -179,6 +169,17 @@ const collaboratorsService = new CollaboratorsService({
whitelist: Whitelist,
})

const infraService = new InfraService({
sitesService,
reposService,
deploymentsService,
launchesService,
queueService,
collaboratorsService,
})
// poller for incoming queue
infraService.pollQueue()

const authenticationMiddleware = getAuthenticationMiddleware()
const authorizationMiddleware = getAuthorizationMiddleware({
identityAuthService,
Expand Down
10 changes: 0 additions & 10 deletions src/services/identity/ReposService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ export default class ReposService {
const repoUrl = `https://github.com/isomerpages/${repoName}`

await this.createRepoOnGithub(repoName)
await this.createTeamOnGitHub(repoName)
await this.generateRepoAndPublishToGitHub(repoName, repoUrl)
return this.create({
name: repoName,
Expand Down Expand Up @@ -148,15 +147,6 @@ export default class ReposService {
private: false,
})

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

setRepoAndTeamPermissions = async (repoName: string): Promise<void> => {
await octokit.repos.updateBranchProtection({
owner: ISOMER_GITHUB_ORGANIZATION_NAME,
Expand Down
7 changes: 7 additions & 0 deletions src/services/identity/UsersService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,13 @@ class UsersService {
return user
}

async findOrCreateByEmail(email: string | undefined) {
const [user] = await this.repository.findOrCreate({
where: { email },
})
return user
}

async login(githubId: string): Promise<User> {
return this.sequelize.transaction<User>(async (transaction) => {
// NOTE: The service's findOrCreate is not being used here as this requires an explicit transaction
Expand Down
25 changes: 23 additions & 2 deletions src/services/infra/InfraService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ReposService from "@services/identity/ReposService"
import SitesService from "@services/identity/SitesService"
import { mailer } from "@services/utilServices/MailClient"

import CollaboratorsService from "../identity/CollaboratorsService"
import QueueService from "../identity/QueueService"

const SITE_LAUNCH_UPDATE_INTERVAL = 30000
Expand All @@ -31,6 +32,7 @@ interface InfraServiceProps {
deploymentsService: DeploymentsService
launchesService: LaunchesService
queueService: QueueService
collaboratorsService: CollaboratorsService
}

interface dnsRecordDto {
Expand All @@ -49,27 +51,45 @@ export default class InfraService {

private readonly queueService: InfraServiceProps["queueService"]

private readonly collaboratorsService: InfraServiceProps["collaboratorsService"]

constructor({
sitesService,
reposService,
deploymentsService,
launchesService,
queueService,
collaboratorsService,
}: InfraServiceProps) {
this.sitesService = sitesService
this.reposService = reposService
this.deploymentsService = deploymentsService
this.launchesService = launchesService
this.queueService = queueService
this.collaboratorsService = collaboratorsService
}

createSite = async (creator: User, siteName: string, repoName: string) => {
createSite = async (
creator: User,
member: User,
siteName: string,
repoName: string
) => {
let site: Site | undefined // For error handling
const memberEmail = member.email
if (!memberEmail) {
logger.error(
`createSite: initial member for ${siteName} does not have associated email`
)
throw new Error(
`createSite: initial member for ${siteName} does not have associated email`
)
}
try {
// 1. Create a new site record in the Sites table
const newSiteParams = {
name: siteName,
apiTokenName: "", // TODO: figure this out
apiTokenName: "", // TODO (IS-76): Remove once DB has removed this param
creator,
creatorId: creator.id,
}
Expand All @@ -96,6 +116,7 @@ export default class InfraService {

// 5. Set up permissions
await this.reposService.setRepoAndTeamPermissions(repoName)
await this.collaboratorsService.create(repoName, memberEmail, true)

// 6. Update status
const updateSuccessSiteInitParams = {
Expand Down

0 comments on commit d7e2788

Please sign in to comment.