mirror of
https://github.com/hcengineering/platform.git
synced 2026-08-24 13:22:23 +02:00
* Get your own integrations for admin Signed-off-by: Artem Savchenko <armisav@gmail.com> * Remove admin check Signed-off-by: Artem Savchenko <armisav@gmail.com> * Clean up Signed-off-by: Artem Savchenko <armisav@gmail.com> * Allow to add social id by admin Signed-off-by: Artem Savchenko <armisav@gmail.com> * Use service token for integrations test Signed-off-by: Artem Savchenko <armisav@gmail.com> * Update version Signed-off-by: Artem Savchenko <armisav@gmail.com> * Fix tokens Signed-off-by: Artem Savchenko <armisav@gmail.com> * Update allowed services Signed-off-by: Artem Savchenko <armisav@gmail.com> * Use workspace service Signed-off-by: Artem Savchenko <armisav@gmail.com> * Fix service client Signed-off-by: Artem Savchenko <armisav@gmail.com> * Get rid of admin service name Signed-off-by: Artem Savchenko <armisav@gmail.com> --------- Signed-off-by: Artem Savchenko <armisav@gmail.com>
161 lines
5.9 KiB
TypeScript
161 lines
5.9 KiB
TypeScript
import { type IntegrationKind, type PersonId, type WorkspaceUuid, systemAccountUuid } from '@hcengineering/core'
|
|
import { getAccountClient } from '@hcengineering/server-client'
|
|
import { generateToken } from '@hcengineering/server-token'
|
|
import { type Integration } from '@hcengineering/account-client'
|
|
import { getDBClient } from '@hcengineering/postgres'
|
|
|
|
const GITHUB_INTEGRATION: IntegrationKind = 'github' as any
|
|
|
|
interface IntegrationSetting {
|
|
workspaceId: WorkspaceUuid
|
|
createdBy: PersonId
|
|
installationIds: number[]
|
|
}
|
|
|
|
export async function restoreGithubIntegrations (dbUrl: string, dryrun: boolean): Promise<void> {
|
|
try {
|
|
const pg = getDBClient(dbUrl)
|
|
const pgClient = await pg.getClient()
|
|
const token = generateToken(systemAccountUuid, undefined, { service: 'tool', admin: 'true' })
|
|
const accountClient = getAccountClient(token)
|
|
|
|
const integrationSettings = await pgClient<
|
|
{ workspaceId: WorkspaceUuid, createdBy: PersonId, installationId: number }[]
|
|
>`
|
|
SELECT "workspaceId", "createdBy", data -> 'installationId' "installationId"
|
|
FROM github
|
|
WHERE _class='github:class:GithubIntegration'
|
|
`
|
|
|
|
// Group by workspace and createdBy, collecting installationIds
|
|
const uniqueSettings = groupIntegrationSettings(integrationSettings)
|
|
console.info('Start restoring GitHub installation IDs v3, count: ', uniqueSettings.length)
|
|
|
|
let createdCount = 0
|
|
let updatedCount = 0
|
|
for (const setting of uniqueSettings) {
|
|
try {
|
|
const isMigratedSocialId = !isNaN(parseInt(setting.createdBy, 10))
|
|
if (!isMigratedSocialId) {
|
|
// Integration should not be affected in this case, since in corrupted migration socialIds were also used to search integrations
|
|
console.info('Skip non-migrated integration:', setting.createdBy, setting.workspaceId)
|
|
continue
|
|
}
|
|
|
|
const existingIntegration = await accountClient.getIntegration({
|
|
workspaceUuid: setting.workspaceId,
|
|
socialId: setting.createdBy,
|
|
kind: GITHUB_INTEGRATION
|
|
})
|
|
|
|
let installationId: number | number[]
|
|
|
|
if (existingIntegration != null) {
|
|
const existingInstallationId = existingIntegration?.data?.installationId
|
|
|
|
// Merge existing and new installation IDs
|
|
const allInstallationIds = new Set<number>()
|
|
if (existingInstallationId != null) {
|
|
if (Array.isArray(existingInstallationId)) {
|
|
existingInstallationId.filter(isValidInstallationId).forEach((id) => allInstallationIds.add(id))
|
|
} else if (isValidInstallationId(existingInstallationId)) {
|
|
allInstallationIds.add(existingInstallationId)
|
|
}
|
|
}
|
|
setting.installationIds.forEach((id) => allInstallationIds.add(id))
|
|
|
|
const mergedIds = Array.from(allInstallationIds)
|
|
installationId = mergedIds.length === 1 ? mergedIds[0] : mergedIds
|
|
|
|
// Check if the merged result is the same as existing
|
|
const isSame = Array.isArray(installationId)
|
|
? Array.isArray(existingInstallationId) &&
|
|
installationId.length === existingInstallationId.length &&
|
|
installationId.every((id) => existingInstallationId.includes(id))
|
|
: existingInstallationId === installationId
|
|
|
|
if (isSame) {
|
|
if (dryrun) {
|
|
console.info('Dry run: skip existing integration', existingIntegration)
|
|
}
|
|
continue
|
|
}
|
|
|
|
const updatedData = {
|
|
...(existingIntegration.data ?? {}),
|
|
installationId
|
|
}
|
|
const updatedIntegration: Integration = {
|
|
...existingIntegration,
|
|
data: updatedData
|
|
}
|
|
if (dryrun) {
|
|
console.info('Dry run: would update integration', existingIntegration, updatedIntegration)
|
|
updatedCount++
|
|
continue
|
|
}
|
|
await accountClient.updateIntegration(updatedIntegration)
|
|
updatedCount++
|
|
} else {
|
|
installationId = setting.installationIds.length === 1 ? setting.installationIds[0] : setting.installationIds
|
|
const integration: Integration = {
|
|
workspaceUuid: setting.workspaceId,
|
|
socialId: setting.createdBy,
|
|
kind: GITHUB_INTEGRATION,
|
|
data: {
|
|
installationId
|
|
}
|
|
}
|
|
if (dryrun) {
|
|
console.info('Dry run: would create integration', integration)
|
|
createdCount++
|
|
continue
|
|
}
|
|
await accountClient.createIntegration(integration)
|
|
createdCount++
|
|
}
|
|
} catch (e: any) {
|
|
console.error('Error restoring GitHub integration', setting.createdBy, setting.workspaceId, e)
|
|
}
|
|
}
|
|
console.info(`Finished restoring GitHub integrations, updated: ${updatedCount}, created: ${createdCount}`)
|
|
} catch (e) {
|
|
console.error('Failed to restore GitHub integrations', e)
|
|
}
|
|
}
|
|
|
|
function groupIntegrationSettings (
|
|
settings: Array<{ workspaceId: WorkspaceUuid, createdBy: PersonId, installationId: number }>
|
|
): IntegrationSetting[] {
|
|
const groupedSettings = new Map<string, IntegrationSetting>()
|
|
|
|
for (const setting of settings) {
|
|
if (setting.installationId == null) continue
|
|
|
|
const key = `${setting.workspaceId}-${setting.createdBy}`
|
|
const existing = groupedSettings.get(key)
|
|
|
|
if (existing != null) {
|
|
if (!existing.installationIds.includes(setting.installationId)) {
|
|
existing.installationIds.push(setting.installationId)
|
|
}
|
|
} else {
|
|
groupedSettings.set(key, {
|
|
workspaceId: setting.workspaceId,
|
|
createdBy: setting.createdBy,
|
|
installationIds: [setting.installationId]
|
|
})
|
|
}
|
|
}
|
|
|
|
return Array.from(groupedSettings.values())
|
|
}
|
|
|
|
function isValidInstallationId (id: any): boolean {
|
|
if (typeof id === 'number' && !isNaN(id) && id > 0) {
|
|
return true
|
|
}
|
|
const parsed = parseInt(String(id), 10)
|
|
return !isNaN(parsed) && parsed > 0
|
|
}
|