UBERF-8587: Fix github auth and delete issues (#7174)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev
2024-11-14 23:30:42 +07:00
committed by GitHub
parent 5ea7ff2667
commit 63294b0c66
10 changed files with 90 additions and 111 deletions
+7 -16
View File
@@ -86,18 +86,9 @@ export async function start (ctx: MeasureContext, brandingMap: BrandingMap): Pro
body: req.body
})
ctx.info('map-installation', {
workspace: decodedToken.workspace.name,
installationid: payloadData.installationId
})
await ctx.withLog('map-installation', {}, async (ctx) => {
await worker.mapInstallation(
ctx,
decodedToken.workspace.name,
payloadData.installationId,
payloadData.accountId
)
})
await ctx.with('map-installation', {}, (ctx) =>
worker.mapInstallation(ctx, decodedToken.workspace.name, payloadData.installationId, payloadData.accountId)
)
res.status(200)
res.json({})
} catch (err: any) {
@@ -136,7 +127,7 @@ export async function start (ctx: MeasureContext, brandingMap: BrandingMap): Pro
code: payloadData.code,
state: payloadData.state
})
await ctx.withLog('request-github-access-token', {}, async (ctx) => {
await ctx.with('request-github-access-token', {}, async (ctx) => {
await worker.requestGithubAccessToken({
workspace: decodedToken.workspace.name,
accountId: payloadData.accountId,
@@ -172,9 +163,9 @@ export async function start (ctx: MeasureContext, brandingMap: BrandingMap): Pro
workspace: decodedToken.workspace.name,
installationId: payloadData.installationId
})
await ctx.withLog('remove-installation', {}, async (ctx) => {
await worker.removeInstallation(ctx, decodedToken.workspace.name, payloadData.installationId)
})
await ctx.with('remove-installation', {}, (ctx) =>
worker.removeInstallation(ctx, decodedToken.workspace.name, payloadData.installationId)
)
res.status(200)
res.json({})
} catch (err: any) {
@@ -734,8 +734,8 @@ export abstract class IssueSyncManagerBase {
await this.ctx.withLog(
'create mixin issue',
{},
async () =>
await this.client.createMixin<Issue, Issue>(
() =>
this.client.createMixin<Issue, Issue>(
existing._id as Ref<GithubIssueP>,
existing._class,
existing.space,
@@ -1259,7 +1259,8 @@ export abstract class IssueSyncManagerBase {
if (!cnt) {
Analytics.handleError(err)
this.ctx.error('Error', { err })
await derivedClient.update(info, { error: errorToObj(err) })
await derivedClient.update(info, { error: errorToObj(err), needSync: githubSyncVersion })
return false
}
}
}
@@ -545,11 +545,8 @@ export class IssueSyncManager extends IssueSyncManagerBase implements DocSyncMan
url: issueExternal.url,
workspace: this.provider.getWorkspaceId().name
})
target.prjData = await this.ctx.withLog(
'add issue to project v2',
{},
async () =>
await this.addIssueToProject(container, okit, issueExternal, target.target.projectNodeId as string)
target.prjData = await this.ctx.withLog('add issue to project v2', {}, () =>
this.addIssueToProject(container, okit, issueExternal, target.target.projectNodeId as string)
)
if (target.prjData !== undefined) {
issueExternal.projectItems.nodes.push(target.prjData)
+18 -30
View File
@@ -129,9 +129,7 @@ export class ProjectsSyncManager implements DocSyncManager {
await this.ctx.withLog(
'Create Milestone projectV2',
{},
async () => {
await this.createMilestone(container.container, container.project, okit, milestone, info)
},
() => this.createMilestone(container.container, container.project, okit, milestone, info),
{ label: milestone.label }
)
} catch (err: any) {
@@ -148,17 +146,9 @@ export class ProjectsSyncManager implements DocSyncManager {
let { projectStructure, wasUpdates } = await this.ctx.withLog(
'update project structure',
{},
async () =>
await syncRunner.exec(
m._id,
async () =>
await this.updateFieldMappings(
container.container,
container.project,
m,
container.project.mixinClass,
okit
)
() =>
syncRunner.exec(m._id, () =>
this.updateFieldMappings(container.container, container.project, m, container.project.mixinClass, okit)
),
{ label: milestone.label }
)
@@ -168,7 +158,7 @@ export class ProjectsSyncManager implements DocSyncManager {
projectStructure = (await this.ctx.withLog(
'update project structure(sync/second step)',
{},
async () => await this.queryProjectStructure(container.container, m),
() => this.queryProjectStructure(container.container, m),
{
label: m.label
}
@@ -340,7 +330,7 @@ export class ProjectsSyncManager implements DocSyncManager {
const projectStructure = (await this.ctx.withLog(
'update project structure(handleEvent)',
{ prj: project.name },
async () => await this.queryProjectStructure(integration, project)
() => this.queryProjectStructure(integration, project)
)) as GithubProjectV2
integration.projectStructure.set(project._id, projectStructure)
@@ -423,20 +413,18 @@ export class ProjectsSyncManager implements DocSyncManager {
let { projectStructure, wasUpdates } = await this.ctx.withLog(
'update project structure',
{ prj: prj.name },
async () => await this.updateFieldMappings(integration, prj, prj, prj.mixinClass, okit)
() => this.updateFieldMappings(integration, prj, prj, prj.mixinClass, okit)
)
// Check if we have any changes in project, during our inactivity.
await this.ctx.withLog('check project v2 changes:', { prj: prj.name }, async () => {
await this.checkChanges(projectStructure, prj, prj._id, integration, derivedClient)
})
await this.ctx.withLog('check project v2 changes:', { prj: prj.name }, () =>
this.checkChanges(projectStructure, prj, prj._id, integration, derivedClient)
)
// Retrieve updated field
if (wasUpdates) {
projectStructure = (await this.ctx.withLog(
'update project structure(second pass)',
{ prj: prj.name },
async () => await this.queryProjectStructure(integration, prj)
projectStructure = (await this.ctx.withLog('update project structure(second pass)', { prj: prj.name }, () =>
this.queryProjectStructure(integration, prj)
)) as GithubProjectV2
}
@@ -459,24 +447,24 @@ export class ProjectsSyncManager implements DocSyncManager {
let { projectStructure, wasUpdates } = await this.ctx.withLog(
'update project structure',
{ prj: m.label },
async () =>
await syncRunner.exec(
() =>
syncRunner.exec(
m._id,
async () => await this.updateFieldMappings(integration, prj, m, prj.mixinClass, okit)
)
)
// Check if we have any changes in project, during our inactivity.
await this.ctx.withLog('check project v2 changes', { prj: prj.name }, async () => {
await this.checkChanges(projectStructure, m, prj._id, integration, derivedClient)
})
await this.ctx.withLog('check project v2 changes', { prj: prj.name }, () =>
this.checkChanges(projectStructure, m, prj._id, integration, derivedClient)
)
// Retrieve updated field
if (wasUpdates) {
projectStructure = (await this.ctx.withLog(
'update project structure(second pass)',
{ prj: prj.name },
async () => await this.queryProjectStructure(integration, m)
() => this.queryProjectStructure(integration, m)
)) as GithubProjectV2
}
@@ -343,12 +343,12 @@ export class PullRequestSyncManager extends IssueSyncManagerBase implements DocS
private async createSyncData (
pullRequestExternal: PullRequestExternalData,
derivedClient: TxOperations | undefined,
derivedClient: TxOperations,
repo: GithubIntegrationRepository,
account: Ref<Account>
): Promise<void> {
const lastModified = new Date(pullRequestExternal.updatedAt).getTime()
await derivedClient?.createDoc(github.class.DocSyncInfo, repo.githubProject as Ref<GithubProject>, {
await derivedClient.createDoc(github.class.DocSyncInfo, repo.githubProject as Ref<GithubProject>, {
url: pullRequestExternal.url.toLowerCase(),
needSync: '', // we need to sync to retrieve patch in background
githubNumber: pullRequestExternal.number,
@@ -426,8 +426,7 @@ export class PullRequestSyncManager extends IssueSyncManagerBase implements DocS
target.prjData = await this.ctx.withLog(
'add pull request to project}',
{},
async () =>
await this.addIssueToProject(container, okit, pullRequestExternal, target.target.projectNodeId as string),
() => this.addIssueToProject(container, okit, pullRequestExternal, target.target.projectNodeId as string),
{ url: pullRequestExternal.url }
)
if (target.prjData !== undefined) {
@@ -575,8 +574,8 @@ export class PullRequestSyncManager extends IssueSyncManagerBase implements DocS
await this.ctx.withLog(
'update pull request patch',
{},
async () => {
await this.handlePatch(
() =>
this.handlePatch(
info,
container,
pullRequestExternal,
@@ -587,8 +586,7 @@ export class PullRequestSyncManager extends IssueSyncManagerBase implements DocS
},
lastModified,
accountGH
)
},
),
{ url: pullRequestExternal.url }
)
}
@@ -606,8 +604,8 @@ export class PullRequestSyncManager extends IssueSyncManagerBase implements DocS
const update = await this.ctx.withLog(
'perform pull request diff update',
{},
async () =>
await this.handleDiffUpdate(
() =>
this.handleDiffUpdate(
target,
{ ...(existing as any), description },
info,
+35 -14
View File
@@ -96,6 +96,8 @@ export class GithubWorker implements IntegrationManager {
triggerRequests: number = 0
authRequestSend = new Set<Ref<Account>>()
triggerSync: () => void = () => {
this.triggerRequests++
}
@@ -546,7 +548,7 @@ export class GithubWorker implements IntegrationManager {
let record = await this.platform.getAccountByRef(this.workspace.name, account)
// const accountRef = this.accounts.find((it) => it._id === account)
const accountRef = await this.liveQuery.findOne(contact.class.PersonAccount, { _id: account })
const [accountRef] = await this.liveQuery.queryFind(contact.class.PersonAccount, { _id: account })
if (record === undefined) {
if (accountRef !== undefined) {
const accounts = this._client.getModel().getAccountByPersonId(accountRef.person)
@@ -570,11 +572,22 @@ export class GithubWorker implements IntegrationManager {
}
// We need to inform user, he need to authorize this account with github.
if (accountRef !== undefined) {
if (accountRef !== undefined && !this.authRequestSend.has(accountRef._id)) {
this.authRequestSend.add(accountRef._id)
const person = await this.liveQuery.findOne(contact.class.Person, { _id: accountRef.person })
if (person !== undefined) {
const personSpace = await this.liveQuery.findOne(contact.class.PersonSpace, { person: person._id })
if (personSpace !== undefined) {
// We need to remove if user has authentication in workspace but doesn't have a record.
const accounts = this._client.getModel().getAccountByPersonId(accountRef.person)
const authentications = await this.liveQuery.findAll(github.class.GithubAuthentication, {
createdBy: { $in: accounts.map((it) => it._id) }
})
for (const auth of authentications) {
await this._client.remove(auth)
}
await createNotification(this._client, person, {
user: account,
space: personSpace._id,
@@ -997,14 +1010,11 @@ export class GithubWorker implements IntegrationManager {
async applyMigrations (): Promise<void> {
const key = 'lowerCaseDuplicates'
// We need to apply migrations if required.
const migration = await this.client.findOne<MigrationState>(core.class.MigrationState, {
plugin: githubId,
state: key
})
const migrations = await this.client.findAll<MigrationState>(core.class.MigrationState, {})
const derivedClient = new TxOperations(this.client, core.account.System, true)
if (migration === undefined) {
if (migrations.find((it) => it.plugin === githubId && it.state === key) === undefined) {
let modifiedOn = 0
const limit = 1000
while (true) {
@@ -1070,6 +1080,21 @@ export class GithubWorker implements IntegrationManager {
state: key
})
}
const wrongAuthentications = 'migrate-wrong-authentications'
if (migrations.find((it) => it.plugin === githubId && it.state === wrongAuthentications) === undefined) {
const auths = await this.client.findAll(github.class.GithubAuthentication, {})
for (const auth of auths) {
if (auth.createdBy !== auth.modifiedBy) {
await this._client.remove(auth)
}
}
await derivedClient.createDoc(core.class.MigrationState, core.space.Configuration, {
plugin: githubId,
state: wrongAuthentications
})
}
}
async syncAndWait (): Promise<void> {
@@ -1328,15 +1353,15 @@ export class GithubWorker implements IntegrationManager {
if (info.deleted === true) {
if (await mapper.handleDelete(existing, info, derivedClient, true)) {
await derivedClient.remove(info)
continue
}
continue
}
const docUpdate = await this.ctx.withLog(
'sync doc',
{},
async (ctx) => await mapper.sync(existing, info, parent, derivedClient),
{ url: info.url.toLowerCase() }
(ctx) => mapper.sync(existing, info, parent, derivedClient),
{ url: info.url.toLowerCase(), workspace: this.workspace.name }
)
if (docUpdate !== undefined) {
await derivedClient.update(info, docUpdate)
@@ -1397,10 +1422,6 @@ export class GithubWorker implements IntegrationManager {
}, 50) // Small timeout to aggregate few bulk changes.
}
}
// Wait up for every 60 seconds to refresh, just in case.
setTimeout(() => {
resolve()
}, 60 * 1000)
})
}