mirror of
https://github.com/hcengineering/platform.git
synced 2025-03-21 23:08:41 +00:00
174 lines
5.1 KiB
TypeScript
174 lines
5.1 KiB
TypeScript
import { createNodeMiddleware } from '@octokit/webhooks'
|
|
import { App } from 'octokit'
|
|
|
|
import config from './config'
|
|
import { PlatformWorker } from './platform'
|
|
|
|
import bp from 'body-parser'
|
|
import cors from 'cors'
|
|
import express from 'express'
|
|
|
|
import { Analytics } from '@hcengineering/analytics'
|
|
import { Account, BrandingMap, MeasureContext, Ref } from '@hcengineering/core'
|
|
import { setMetadata } from '@hcengineering/platform'
|
|
import serverClient from '@hcengineering/server-client'
|
|
import serverCore from '@hcengineering/server-core'
|
|
import { decodeToken } from '@hcengineering/server-token'
|
|
|
|
/**
|
|
* @public
|
|
*/
|
|
export async function start (ctx: MeasureContext, brandingMap: BrandingMap): Promise<void> {
|
|
// Create an authenticated Octokit client authenticated as a GitHub App
|
|
ctx.info('Running Huly Github integration', { appId: config.AppID, clientID: config.ClientID })
|
|
|
|
setMetadata(serverCore.metadata.FrontUrl, config.FrontURL)
|
|
setMetadata(serverClient.metadata.Endpoint, config.AccountsURL)
|
|
setMetadata(serverClient.metadata.UserAgent, config.ServiceID)
|
|
|
|
const octokitApp: App = new App({
|
|
appId: config.AppID,
|
|
privateKey: config.PrivateKey,
|
|
webhooks: {
|
|
secret: config.WebhookSecret
|
|
}
|
|
})
|
|
|
|
// Optional: Get & log the authenticated app's name
|
|
const { data } = await octokitApp.octokit.request('/app')
|
|
|
|
// Read more about custom logging: https://github.com/octokit/core.js#logging
|
|
octokitApp.octokit.log.debug(`Authenticated as '${data.name as string}'`)
|
|
|
|
// Optional: Handle errors
|
|
octokitApp.webhooks.onError((error) => {
|
|
Analytics.handleError(error)
|
|
ctx.error('error', { error, event: error.event })
|
|
})
|
|
|
|
// Launch a web server to listen for GitHub webhooks
|
|
const port = config.Port
|
|
const path = '/api/webhook'
|
|
const localWebhookUrl = `http://localhost:${port}${path}`
|
|
|
|
// See https://github.com/octokit/webhooks.js/#createnodemiddleware for all options
|
|
const middleware = createNodeMiddleware(octokitApp.webhooks as any, { path })
|
|
|
|
const app = express()
|
|
|
|
app.use(middleware as any)
|
|
app.use(cors())
|
|
app.use(bp.json())
|
|
app.use(bp.urlencoded({ extended: true }))
|
|
|
|
// Initialize platform worker
|
|
let worker: PlatformWorker
|
|
try {
|
|
worker = await PlatformWorker.create(ctx, octokitApp, brandingMap)
|
|
} catch (err: any) {
|
|
Analytics.handleError(err)
|
|
ctx.error('Failed to init Service', { err })
|
|
process.exit(1)
|
|
}
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
app.post('/api/v1/installation', async (req, res) => {
|
|
try {
|
|
const payloadData: {
|
|
installationId: number
|
|
accountId: Ref<Account>
|
|
token: string
|
|
} = req.body
|
|
|
|
const decodedToken = decodeToken(payloadData.token)
|
|
ctx.info('/api/v1/installation', {
|
|
email: decodedToken.email,
|
|
workspaceName: decodedToken.workspace.name,
|
|
body: req.body
|
|
})
|
|
|
|
await ctx.withLog('map-installation', {}, async (ctx) => {
|
|
await worker.mapInstallation(
|
|
ctx,
|
|
decodedToken.workspace.name,
|
|
payloadData.installationId,
|
|
payloadData.accountId
|
|
)
|
|
})
|
|
res.status(200)
|
|
res.json({})
|
|
} catch (err: any) {
|
|
Analytics.handleError(err)
|
|
res.status(401)
|
|
res.json({ error: err.message })
|
|
}
|
|
})
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
app.post('/api/v1/auth', async (req, res) => {
|
|
try {
|
|
const payloadData: {
|
|
code: string
|
|
state: string
|
|
accountId: Ref<Account>
|
|
token: string
|
|
} = req.body
|
|
|
|
const decodedData: {
|
|
accountId: Ref<Account>
|
|
token: string
|
|
op: string
|
|
} = JSON.parse(atob(payloadData.state))
|
|
|
|
const decodedToken = decodeToken(decodedData.token)
|
|
|
|
await ctx.withLog('request-github-access-token', {}, async (ctx) => {
|
|
await worker.requestGithubAccessToken({
|
|
workspace: decodedToken.workspace.name,
|
|
accountId: payloadData.accountId,
|
|
code: payloadData.code,
|
|
state: payloadData.state
|
|
})
|
|
})
|
|
res.status(200)
|
|
res.json({})
|
|
} catch (err: any) {
|
|
Analytics.handleError(err)
|
|
res.status(401)
|
|
res.json({ error: err.message })
|
|
}
|
|
})
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
app.post('/api/v1/installation-remove', async (req, res) => {
|
|
try {
|
|
const payloadData: {
|
|
installationId: number
|
|
token: string
|
|
} = req.body
|
|
|
|
const decodedToken = decodeToken(payloadData.token)
|
|
ctx.info('/api/v1/installation-remove', {
|
|
email: decodedToken.email,
|
|
workspaceName: decodedToken.workspace.name,
|
|
body: req.body
|
|
})
|
|
|
|
await ctx.withLog('map-installation', {}, async (ctx) => {
|
|
await worker.removeInstallation(ctx, decodedToken.workspace.name, payloadData.installationId)
|
|
})
|
|
res.status(200)
|
|
res.json({})
|
|
} catch (err: any) {
|
|
Analytics.handleError(err)
|
|
res.status(401)
|
|
res.json({ error: err.message })
|
|
}
|
|
})
|
|
|
|
app.listen(port, () => {
|
|
ctx.info(`Server is listening for events at: ${localWebhookUrl}`)
|
|
ctx.info('Press Ctrl + C to quit.')
|
|
})
|
|
}
|