From 96d80a1651457359ca409ca270e189a45992db6d Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Mon, 5 Aug 2024 13:03:25 +0700 Subject: [PATCH] UBERF-7800: Space improvements (#6250) Signed-off-by: Andrey Sobolev --- server/middleware/src/spaceSecurity.ts | 105 +++++++++++-------------- 1 file changed, 47 insertions(+), 58 deletions(-) diff --git a/server/middleware/src/spaceSecurity.ts b/server/middleware/src/spaceSecurity.ts index 1ecacebb91..c5985fd9ea 100644 --- a/server/middleware/src/spaceSecurity.ts +++ b/server/middleware/src/spaceSecurity.ts @@ -325,43 +325,6 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar return res } - private async getTxTargets (ctx: SessionContext, tx: Tx): Promise { - const h = this.storage.hierarchy - let targets: string[] | undefined - - if (TxProcessor.isExtendsCUD(tx._class)) { - const account = await getUser(this.storage, ctx) - if (tx.objectSpace === (account._id as string)) { - targets = [account.email, systemAccountEmail] - } else if ([...this.systemSpaces, ...this.mainSpaces].includes(tx.objectSpace)) { - return - } else { - const cudTx = tx as TxCUD - const isSpace = h.isDerived(cudTx.objectClass, core.class.Space) - - if (isSpace) { - return undefined - } - - const space = this.spacesMap.get(tx.objectSpace) - - if (space !== undefined) { - targets = await this.getTargets(space.members) - if (!isOwner(account, ctx)) { - const allowed = this.getAllAllowedSpaces(account, true) - if (allowed === undefined || !allowed.includes(tx.objectSpace)) { - throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {})) - } - } else if (!targets.includes(account.email)) { - targets.push(account.email) - } - } - } - } - - return targets - } - private async processTxSpaceDomain (tx: TxCUD): Promise { const actualTx = TxProcessor.extractTx(tx) if (actualTx._class === core.class.TxCreateDoc) { @@ -450,15 +413,10 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar return isData ? res : [...res, ...this.publicSpaces] } - async loadDomainSpaces (ctx: MeasureContext, domain: Domain): Promise>> { - const field = this.getKey(domain) - return await this.storage.groupBy>(ctx, domain, field) - } - async getDomainSpaces (domain: Domain): Promise>> { let domainSpaces = this._domainSpaces.get(domain) if (domainSpaces === undefined) { - const p = this.loadDomainSpaces(this.spaceMeasureCtx, domain) + const p = this.storage.groupBy>(this.spaceMeasureCtx, domain, this.getKey(domain)) this._domainSpaces.set(domain, p) domainSpaces = await p this._domainSpaces.set(domain, domainSpaces) @@ -466,9 +424,17 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar return domainSpaces instanceof Promise ? await domainSpaces : domainSpaces } - private async filterByDomain (domain: Domain, spaces: Ref[]): Promise[]> { + private async filterByDomain ( + domain: Domain, + spaces: Ref[] + ): Promise<{ result: Ref[], allDomainSpaces: boolean, domainSpaces: Set> }> { const domainSpaces = await this.getDomainSpaces(domain) - return spaces.filter((p) => domainSpaces.has(p)) + const result = spaces.filter((p) => domainSpaces.has(p)) + return { + result: spaces.filter((p) => domainSpaces.has(p)), + allDomainSpaces: result.length === domainSpaces.size, + domainSpaces + } } private async mergeQuery( @@ -476,19 +442,33 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar query: ObjQueryType, domain: Domain, isSpace: boolean - ): Promise> { + ): Promise | undefined> { const spaces = await this.filterByDomain(domain, this.getAllAllowedSpaces(account, !isSpace)) if (query == null) { - return { $in: spaces } + if (spaces.allDomainSpaces) { + return undefined + } + return { $in: spaces.result } } if (typeof query === 'string') { - if (!spaces.includes(query)) { + if (!spaces.result.includes(query)) { return { $in: [] } } } else if (query.$in != null) { - query.$in = query.$in.filter((p) => spaces.includes(p)) + query.$in = query.$in.filter((p) => spaces.result.includes(p)) + if (query.$in.length === spaces.domainSpaces.size) { + // all domain spaces + delete query.$in + } } else { - query.$in = spaces + if (spaces.allDomainSpaces) { + delete query.$in + } else { + query.$in = spaces.result + } + } + if (Object.keys(query).length === 0) { + return undefined } return query } @@ -515,22 +495,31 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar if (!isOwner(account, ctx) || !isSpace) { if (query[field] !== undefined) { const res = await this.mergeQuery(account, query[field], domain, isSpace) - ;(newQuery as any)[field] = res - if (typeof res === 'object') { - if (Array.isArray(res.$in) && res.$in.length === 1 && Object.keys(res).length === 1) { - ;(newQuery as any)[field] = res.$in[0] + if (res === undefined) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete (query as any)[field] + } else { + ;(newQuery as any)[field] = res + if (typeof res === 'object') { + if (Array.isArray(res.$in) && res.$in.length === 1 && Object.keys(res).length === 1) { + ;(newQuery as any)[field] = res.$in[0] + } } } } else { const spaces = await this.filterByDomain(domain, this.getAllAllowedSpaces(account, !isSpace)) - if (spaces.length === 1) { - ;(newQuery as any)[field] = spaces[0] + if (spaces.allDomainSpaces) { + // eslint-disable-next-line @typescript-eslint/no-dynamic-delete + delete (newQuery as any)[field] + } else if (spaces.result.length === 1) { + ;(newQuery as any)[field] = spaces.result[0] } else { - ;(newQuery as any)[field] = { $in: spaces } + ;(newQuery as any)[field] = { $in: spaces.result } } } } } + const findResult = await this.provideFindAll(ctx, _class, newQuery, options) if (!isOwner(account, ctx) && account.role !== AccountRole.DocGuest) { if (options?.lookup !== undefined) { @@ -564,7 +553,7 @@ export class SpaceSecurityMiddleware extends BaseMiddleware implements Middlewar } passedDomains.add(domain) const spaces = await this.filterByDomain(domain, allSpaces) - for (const space of spaces) { + for (const space of spaces.result) { res.add(space) } }