UBERF-5000: Handle derived tx for security context update (#4391)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2024-01-19 22:43:37 +07:00 committed by GitHub
parent 85a68bebb9
commit 8d9856557c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 63 additions and 11 deletions

View File

@ -23,16 +23,16 @@ import {
MeasureContext, MeasureContext,
ModelDb, ModelDb,
Ref, Ref,
SearchOptions,
SearchQuery,
SearchResult,
ServerStorage, ServerStorage,
StorageIterator, StorageIterator,
Tx, Tx,
TxResult, TxResult
SearchQuery,
SearchOptions,
SearchResult
} from '@hcengineering/core' } from '@hcengineering/core'
import { DbConfiguration, createServerStorage } from './storage' import { DbConfiguration, createServerStorage } from './storage'
import { BroadcastFunc, Middleware, MiddlewareCreator, Pipeline, SessionContext } from './types' import { BroadcastFunc, HandledBroadcastFunc, Middleware, MiddlewareCreator, Pipeline, SessionContext } from './types'
/** /**
* @public * @public
@ -44,12 +44,22 @@ export async function createPipeline (
upgrade: boolean, upgrade: boolean,
broadcast: BroadcastFunc broadcast: BroadcastFunc
): Promise<Pipeline> { ): Promise<Pipeline> {
let broadcastHook: HandledBroadcastFunc = (): Tx[] => {
return []
}
const storage = await createServerStorage(conf, { const storage = await createServerStorage(conf, {
upgrade, upgrade,
broadcast broadcast: (tx: Tx[], targets?: string[]) => {
const sendTx = broadcastHook?.(tx, targets) ?? tx
broadcast(sendTx, targets)
}
}) })
const pipeline = PipelineImpl.create(ctx, storage, constructors, broadcast) const pipeline = PipelineImpl.create(ctx, storage, constructors, broadcast)
return await pipeline const pipelineResult = await pipeline
broadcastHook = (tx, targets) => {
return pipelineResult.handleBroadcast(tx, targets)
}
return pipelineResult
} }
class PipelineImpl implements Pipeline { class PipelineImpl implements Pipeline {
@ -59,6 +69,10 @@ class PipelineImpl implements Pipeline {
this.modelDb = storage.modelDb this.modelDb = storage.modelDb
} }
handleBroadcast (tx: Tx[], targets?: string[]): Tx[] {
return this.head?.handleBroadcast(tx, targets) ?? tx
}
static async create ( static async create (
ctx: MeasureContext, ctx: MeasureContext,
storage: ServerStorage, storage: ServerStorage,

View File

@ -64,12 +64,18 @@ export interface Middleware {
options?: FindOptions<T> options?: FindOptions<T>
) => Promise<FindResult<T>> ) => Promise<FindResult<T>>
searchFulltext: (ctx: SessionContext, query: SearchQuery, options: SearchOptions) => Promise<SearchResult> searchFulltext: (ctx: SessionContext, query: SearchQuery, options: SearchOptions) => Promise<SearchResult>
handleBroadcast: (tx: Tx[], targets?: string[]) => Tx[]
} }
/** /**
* @public * @public
*/ */
export type BroadcastFunc = (tx: Tx[], targets?: string[]) => void export type BroadcastFunc = (tx: Tx[], targets?: string[]) => void
/**
* @public
*/
export type HandledBroadcastFunc = (tx: Tx[], targets?: string[]) => Tx[]
/** /**
* @public * @public

View File

@ -20,11 +20,11 @@ import {
FindOptions, FindOptions,
FindResult, FindResult,
Ref, Ref,
ServerStorage,
Tx,
SearchQuery,
SearchOptions, SearchOptions,
SearchResult SearchQuery,
SearchResult,
ServerStorage,
Tx
} from '@hcengineering/core' } from '@hcengineering/core'
import { Middleware, SessionContext, TxMiddlewareResult } from '@hcengineering/server-core' import { Middleware, SessionContext, TxMiddlewareResult } from '@hcengineering/server-core'
@ -58,6 +58,13 @@ export abstract class BaseMiddleware {
return [res[0], res[1], undefined] return [res[0], res[1], undefined]
} }
provideHandleBroadcast (tx: Tx[], targets?: string[]): Tx[] {
if (this.next !== undefined) {
return this.next.handleBroadcast(tx, targets)
}
return tx
}
protected async provideFindAll<T extends Doc>( protected async provideFindAll<T extends Doc>(
ctx: SessionContext, ctx: SessionContext,
_class: Ref<Class<T>>, _class: Ref<Class<T>>,

View File

@ -68,6 +68,10 @@ export class ConfigurationMiddleware extends BaseMiddleware implements Middlewar
return await this.provideTx(ctx, tx) return await this.provideTx(ctx, tx)
} }
handleBroadcast (tx: Tx[], targets?: string[]): Tx[] {
return this.provideHandleBroadcast(tx, targets)
}
override async findAll<T extends Doc>( override async findAll<T extends Doc>(
ctx: SessionContext, ctx: SessionContext,
_class: Ref<Class<T>>, _class: Ref<Class<T>>,

View File

@ -34,6 +34,10 @@ export class ModifiedMiddleware extends BaseMiddleware implements Middleware {
return new ModifiedMiddleware(storage, next) return new ModifiedMiddleware(storage, next)
} }
handleBroadcast (tx: Tx[], targets?: string[]): Tx[] {
return this.provideHandleBroadcast(tx, targets)
}
async tx (ctx: SessionContext, tx: Tx): Promise<TxMiddlewareResult> { async tx (ctx: SessionContext, tx: Tx): Promise<TxMiddlewareResult> {
if (tx.modifiedBy !== core.account.System && ctx.userEmail !== systemAccountEmail) { if (tx.modifiedBy !== core.account.System && ctx.userEmail !== systemAccountEmail) {
tx.modifiedOn = Date.now() tx.modifiedOn = Date.now()

View File

@ -75,6 +75,10 @@ export class PrivateMiddleware extends BaseMiddleware implements Middleware {
return [res[0], res[1], mergeTargets(target, res[2])] return [res[0], res[1], mergeTargets(target, res[2])]
} }
handleBroadcast (tx: Tx[], targets?: string[]): Tx[] {
return this.provideHandleBroadcast(tx, targets)
}
override async findAll<T extends Doc>( override async findAll<T extends Doc>(
ctx: SessionContext, ctx: SessionContext,
_class: Ref<Class<T>>, _class: Ref<Class<T>>,

View File

@ -60,6 +60,10 @@ export class QueryJoinMiddleware extends BaseMiddleware implements Middleware {
return await this.provideTx(ctx, tx) return await this.provideTx(ctx, tx)
} }
handleBroadcast (tx: Tx[], targets?: string[]): Tx[] {
return this.provideHandleBroadcast(tx, targets)
}
override async findAll<T extends Doc>( override async findAll<T extends Doc>(
ctx: SessionContext, ctx: SessionContext,
_class: Ref<Class<T>>, _class: Ref<Class<T>>,

View File

@ -398,6 +398,15 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar
return [res[0], res[1], mergeTargets(targets, res[2])] return [res[0], res[1], mergeTargets(targets, res[2])]
} }
handleBroadcast (tx: Tx[], targets?: string[]): Tx[] {
for (const t of tx) {
if (this.storage.hierarchy.isDerived(t._class, core.class.TxCUD)) {
this.processTxSpaceDomain(t as TxCUD<Doc>)
}
}
return this.provideHandleBroadcast(tx, targets)
}
private getAllAllowedSpaces (account: Account): Ref<Space>[] { private getAllAllowedSpaces (account: Account): Ref<Space>[] {
let userSpaces: Ref<Space>[] = [] let userSpaces: Ref<Space>[] = []
try { try {