From c94076087dc842c949fd19237bc292862d7fed14 Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Fri, 12 Jul 2024 20:10:33 +0700 Subject: [PATCH] UBERF-7583: Fix workspace upgrade (#6062) Signed-off-by: Andrey Sobolev --- packages/core/src/operations.ts | 4 ++-- packages/core/src/tx.ts | 10 ++++++++++ packages/presentation/src/utils.ts | 2 +- plugins/view-resources/src/middleware.ts | 2 +- server-plugins/openai/src/resources.ts | 2 +- server/core/src/fulltext.ts | 3 ++- server/core/src/server/storage.ts | 11 +++++++---- server/middleware/src/configuration.ts | 5 +++-- server/middleware/src/private.ts | 5 +++-- server/middleware/src/spacePermissions.ts | 6 ++---- server/middleware/src/spaceSecurity.ts | 7 +++---- server/tool/src/index.ts | 17 +++++++++++++++++ server/ws/src/client.ts | 4 ++-- 13 files changed, 54 insertions(+), 24 deletions(-) diff --git a/packages/core/src/operations.ts b/packages/core/src/operations.ts index d3271ecc3a..94e45c3ec9 100644 --- a/packages/core/src/operations.ts +++ b/packages/core/src/operations.ts @@ -453,7 +453,7 @@ export class ApplyOperations extends TxOperations { findAll: (_class, query, options?) => ops.client.findAll(_class, query, options), searchFulltext: (query, options) => ops.client.searchFulltext(query, options), tx: async (tx): Promise => { - if (ops.getHierarchy().isDerived(tx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(tx._class)) { this.txes.push(tx as TxCUD) } return {} @@ -518,7 +518,7 @@ export class TxBuilder extends TxOperations { findAll: async (_class, query, options?) => toFindResult([]), searchFulltext: async (query, options) => ({ docs: [] }), tx: async (tx): Promise => { - if (this.hierarchy.isDerived(tx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(tx._class)) { this.txes.push(tx as TxCUD) } return {} diff --git a/packages/core/src/tx.ts b/packages/core/src/tx.ts index d14d85704c..8d5d24ff9c 100644 --- a/packages/core/src/tx.ts +++ b/packages/core/src/tx.ts @@ -438,6 +438,16 @@ export abstract class TxProcessor implements WithTx { return doc as D } + static isExtendsCUD (_class: Ref>): boolean { + return ( + _class === core.class.TxCreateDoc || + _class === core.class.TxUpdateDoc || + _class === core.class.TxRemoveDoc || + _class === core.class.TxCollectionCUD || + _class === core.class.TxMixin + ) + } + static extractTx (tx: Tx): Tx { if (tx._class === core.class.TxCollectionCUD) { const ctx = tx as TxCollectionCUD diff --git a/packages/presentation/src/utils.ts b/packages/presentation/src/utils.ts index 37e195e6d3..1b8f61d333 100644 --- a/packages/presentation/src/utils.ts +++ b/packages/presentation/src/utils.ts @@ -200,7 +200,7 @@ class UIClient extends TxOperations implements Client, OptimisticTxes { return } - if (!this.getHierarchy().isDerived(tx._class, core.class.TxCUD)) { + if (!TxProcessor.isExtendsCUD(tx._class)) { return } diff --git a/plugins/view-resources/src/middleware.ts b/plugins/view-resources/src/middleware.ts index 09d1f10f82..94201e46c2 100644 --- a/plugins/view-resources/src/middleware.ts +++ b/plugins/view-resources/src/middleware.ts @@ -303,7 +303,7 @@ export class AnalyticsMiddleware extends BasePresentationMiddleware implements P const applyIf = etx as TxApplyIf void this.handleTx(...applyIf.txes) } - if (this.client.getHierarchy().isDerived(etx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(etx._class)) { const cud = etx as TxCUD const _class = this.client.getHierarchy().getClass(cud.objectClass) if (_class.label !== undefined) { diff --git a/server-plugins/openai/src/resources.ts b/server-plugins/openai/src/resources.ts index 8ad7929dc9..359ef7e20f 100644 --- a/server-plugins/openai/src/resources.ts +++ b/server-plugins/openai/src/resources.ts @@ -115,7 +115,7 @@ async function performCompletion ( export async function AsyncOnGPTRequest (tx: Tx, tc: TriggerControl): Promise { const actualTx = TxProcessor.extractTx(tx) - if (tc.hierarchy.isDerived(actualTx._class, core.class.TxCUD) && actualTx.modifiedBy !== openai.account.GPT) { + if (TxProcessor.isExtendsCUD(actualTx._class) && actualTx.modifiedBy !== openai.account.GPT) { const cud: TxCUD = actualTx as TxCUD // if (tc.hierarchy.isDerived(cud.objectClass, chunter.class.ChatMessage)) { diff --git a/server/core/src/fulltext.ts b/server/core/src/fulltext.ts index 358c6fc0e9..9e18f1c55f 100644 --- a/server/core/src/fulltext.ts +++ b/server/core/src/fulltext.ts @@ -33,6 +33,7 @@ import core, { type TxCUD, type TxCollectionCUD, TxFactory, + TxProcessor, type TxResult, type WorkspaceId, docKey, @@ -84,7 +85,7 @@ export class FullTextIndex implements WithFind { attachedToClass = txcol.objectClass tx = txcol.tx } - if (this.hierarchy.isDerived(tx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(tx._class)) { const cud = tx as TxCUD if (!isClassIndexable(this.hierarchy, cud.objectClass)) { diff --git a/server/core/src/server/storage.ts b/server/core/src/server/storage.ts index 5d2fc7e3ce..9e17fa77e0 100644 --- a/server/core/src/server/storage.ts +++ b/server/core/src/server/storage.ts @@ -255,7 +255,7 @@ export class TServerStorage implements ServerStorage { for (const tx of txes) { const txCUD = TxProcessor.extractTx(tx) as TxCUD - if (!this.hierarchy.isDerived(txCUD._class, core.class.TxCUD)) { + if (!TxProcessor.isExtendsCUD(txCUD._class)) { // Skip unsupported tx ctx.error('Unsupported transaction', tx) continue @@ -444,6 +444,9 @@ export class TServerStorage implements ServerStorage { if (query?.$search !== undefined) { return await ctx.with(p + '-fulltext-find-all', {}, (ctx) => this.fulltext.findAll(ctx, clazz, query, options)) } + if (domain === DOMAIN_MODEL) { + return this.modelDb.findAllSync(clazz, query, options) + } const st = Date.now() const result = await ctx.with( p + '-find-all', @@ -656,11 +659,11 @@ export class TServerStorage implements ServerStorage { ): Promise => { const classes = new Set>>() for (const dtx of derived) { - if (this.hierarchy.isDerived(dtx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(dtx._class)) { classes.add((dtx as TxCUD).objectClass) } const etx = TxProcessor.extractTx(dtx) - if (this.hierarchy.isDerived(etx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(etx._class)) { classes.add((etx as TxCUD).objectClass) } } @@ -876,7 +879,7 @@ export class TServerStorage implements ServerStorage { for (const tx of txes) { if (!this.hierarchy.isDerived(tx._class, core.class.TxApplyIf)) { if (tx.space !== core.space.DerivedTx) { - if (this.hierarchy.isDerived(tx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(tx._class)) { const objectClass = (tx as TxCUD).objectClass if ( objectClass !== core.class.BenchmarkDoc && diff --git a/server/middleware/src/configuration.ts b/server/middleware/src/configuration.ts index 97a3a62e6e..21411b83d2 100644 --- a/server/middleware/src/configuration.ts +++ b/server/middleware/src/configuration.ts @@ -25,7 +25,8 @@ import core, { MeasureContext, Ref, Tx, - TxCUD + TxCUD, + TxProcessor } from '@hcengineering/core' import platform, { PlatformError, Severity, Status } from '@hcengineering/platform' import { Middleware, SessionContext, TxMiddlewareResult, type ServerStorage } from '@hcengineering/server-core' @@ -51,7 +52,7 @@ export class ConfigurationMiddleware extends BaseMiddleware implements Middlewar } async tx (ctx: SessionContext, tx: Tx): Promise { - if (this.storage.hierarchy.isDerived(tx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(tx._class)) { const txCUD = tx as TxCUD const domain = this.storage.hierarchy.getDomain(txCUD.objectClass) if (this.targetDomains.includes(domain)) { diff --git a/server/middleware/src/private.ts b/server/middleware/src/private.ts index 1e76eeaf3d..f7659cddac 100644 --- a/server/middleware/src/private.ts +++ b/server/middleware/src/private.ts @@ -26,6 +26,7 @@ import core, { Ref, Tx, TxCUD, + TxProcessor, systemAccountEmail } from '@hcengineering/core' import platform, { PlatformError, Severity, Status } from '@hcengineering/platform' @@ -50,7 +51,7 @@ export class PrivateMiddleware extends BaseMiddleware implements Middleware { async tx (ctx: SessionContext, tx: Tx): Promise { let target: string[] | undefined - if (this.storage.hierarchy.isDerived(tx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(tx._class)) { const txCUD = tx as TxCUD const domain = this.storage.hierarchy.getDomain(txCUD.objectClass) if (this.targetDomains.includes(domain)) { @@ -98,7 +99,7 @@ export class PrivateMiddleware extends BaseMiddleware implements Middleware { ) ;(findResult as FindResult as FindResult).filter( (p) => - !hierarchy.isDerived(p._class, core.class.TxCUD) || + !TxProcessor.isExtendsCUD(p._class) || !targetClasses.has((p as TxCUD).objectClass) || p.createdBy === account._id ) diff --git a/server/middleware/src/spacePermissions.ts b/server/middleware/src/spacePermissions.ts index 951a5e8852..abc3a13d51 100644 --- a/server/middleware/src/spacePermissions.ts +++ b/server/middleware/src/spacePermissions.ts @@ -250,9 +250,8 @@ export class SpacePermissionsMiddleware extends BaseMiddleware implements Middle return } - const h = this.storage.hierarchy const actualTx = TxProcessor.extractTx(tx) - if (!h.isDerived(actualTx._class, core.class.TxCUD)) { + if (!TxProcessor.isExtendsCUD(actualTx._class)) { return } @@ -322,8 +321,7 @@ export class SpacePermissionsMiddleware extends BaseMiddleware implements Middle } private async processPermissionsUpdatesFromTx (ctx: SessionContext, tx: Tx): Promise { - const h = this.storage.hierarchy - if (!h.isDerived(tx._class, core.class.TxCUD)) { + if (!TxProcessor.isExtendsCUD(tx._class)) { return } diff --git a/server/middleware/src/spaceSecurity.ts b/server/middleware/src/spaceSecurity.ts index 3084bef302..fd42b700a1 100644 --- a/server/middleware/src/spaceSecurity.ts +++ b/server/middleware/src/spaceSecurity.ts @@ -328,7 +328,7 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar const h = this.storage.hierarchy let targets: string[] | undefined - if (h.isDerived(tx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(tx._class)) { const account = await getUser(this.storage, ctx) if (tx.objectSpace === (account._id as string)) { targets = [account.email, systemAccountEmail] @@ -384,7 +384,7 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar private async processTx (ctx: SessionContext, tx: Tx): Promise { const h = this.storage.hierarchy - if (h.isDerived(tx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(tx._class)) { const cudTx = tx as TxCUD const isSpace = h.isDerived(cudTx.objectClass, core.class.Space) if (isSpace) { @@ -429,8 +429,7 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar exclude?: string[] | undefined ): Promise { for (const tx of txes) { - const h = this.storage.hierarchy - if (h.isDerived(tx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(tx._class)) { // TODO: Do we need security check here? const cudTx = tx as TxCUD await this.processTxSpaceDomain(cudTx) diff --git a/server/tool/src/index.ts b/server/tool/src/index.ts index aa6c6da530..2708e5488f 100644 --- a/server/tool/src/index.ts +++ b/server/tool/src/index.ts @@ -28,6 +28,8 @@ import core, { MeasureContext, MigrationState, ModelDb, + systemAccountEmail, + toWorkspaceString, Tx, WorkspaceId, type Doc, @@ -44,6 +46,7 @@ import toolPlugin from './plugin' import { MigrateClientImpl } from './upgrade' import { getMetadata } from '@hcengineering/platform' +import { generateToken } from '@hcengineering/server-token' import fs from 'fs' import path from 'path' @@ -411,6 +414,20 @@ export async function upgradeModel ( i++ } }) + + if (connection === undefined) { + // We need to send reboot for workspace + console.info('send force close') + const serverEndpoint = transactorUrl.replaceAll('wss://', 'https://').replace('ws://', 'http://') + const token = generateToken(systemAccountEmail, workspaceId, { admin: 'true' }) + await fetch( + serverEndpoint + + `/api/v1/manage?token=${token}&operation=force-close&wsId=${toWorkspaceString(workspaceId, '@')}`, + { + method: 'PUT' + } + ) + } } finally { await connection?.sendForceClose() await connection?.close() diff --git a/server/ws/src/client.ts b/server/ws/src/client.ts index 204885a0b6..789960c71c 100644 --- a/server/ws/src/client.ts +++ b/server/ws/src/client.ts @@ -305,11 +305,11 @@ export class ClientSession implements Session { ): Promise { const classes = new Set>>() for (const dtx of derived) { - if (this._pipeline.storage.hierarchy.isDerived(dtx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(dtx._class)) { classes.add((dtx as TxCUD).objectClass) } const etx = TxProcessor.extractTx(dtx) - if (this._pipeline.storage.hierarchy.isDerived(etx._class, core.class.TxCUD)) { + if (TxProcessor.isExtendsCUD(etx._class)) { classes.add((etx as TxCUD).objectClass) } }