-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'develop' into wingback
- Loading branch information
Showing
69 changed files
with
1,947 additions
and
871 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
import { AlkemioErrorStatus, LogContext } from '@common/enums'; | ||
import { BaseException } from './base.exception'; | ||
import { ExceptionDetails } from '@common/exceptions/exception.details'; | ||
|
||
export class ForbiddenException extends BaseException { | ||
constructor(error: string, context: LogContext, code?: AlkemioErrorStatus) { | ||
super(error, context, code ?? AlkemioErrorStatus.FORBIDDEN); | ||
constructor(error: string, context: LogContext, details?: ExceptionDetails) { | ||
super(error, context, AlkemioErrorStatus.FORBIDDEN, details); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/** | ||
* Compares two TypeScript enums for equality | ||
* @param enum1 First enum to compare | ||
* @param enum2 Second enum to compare | ||
* @returns boolean indicating if enums are equal | ||
*/ | ||
export const compareEnums = <T extends { [key: string]: string | number }>( | ||
enum1: T, | ||
enum2: T | ||
): boolean => { | ||
const keys1 = Object.keys(enum1); | ||
const keys2 = Object.keys(enum2); | ||
|
||
if (keys1.length !== keys2.length) { | ||
return false; | ||
} | ||
|
||
for (const key of keys1) { | ||
if (enum1[key] !== enum2[key]) { | ||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
src/core/dataloader/creators/loader.creators/in-app-notification/callout.loader.creator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { EntityManager, In } from 'typeorm'; | ||
import { Injectable } from '@nestjs/common'; | ||
import { InjectEntityManager } from '@nestjs/typeorm'; | ||
import { DataLoaderCreator } from '@core/dataloader/creators/base'; | ||
import { createBatchLoader } from '@core/dataloader/utils'; | ||
import { ILoader } from '@core/dataloader/loader.interface'; | ||
import { Callout, ICallout } from '@domain/collaboration/callout'; | ||
|
||
@Injectable() | ||
export class CalloutLoaderCreator implements DataLoaderCreator<ICallout> { | ||
constructor(@InjectEntityManager() private manager: EntityManager) {} | ||
|
||
public create(): ILoader<ICallout> { | ||
return createBatchLoader( | ||
this.constructor.name, | ||
Callout.name, | ||
this.calloutInBatch | ||
); | ||
} | ||
|
||
private calloutInBatch = ( | ||
keys: ReadonlyArray<string> | ||
): Promise<Callout[]> => { | ||
return this.manager.findBy(Callout, { id: In(keys) }); | ||
}; | ||
} |
51 changes: 51 additions & 0 deletions
51
.../dataloader/creators/loader.creators/in-app-notification/community.type.loader.creator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { EntityManager } from 'typeorm'; | ||
import { Injectable } from '@nestjs/common'; | ||
import { InjectEntityManager } from '@nestjs/typeorm'; | ||
import { CommunityContributorType } from '@common/enums/community.contributor.type'; | ||
import { DataLoaderCreator } from '@core/dataloader/creators/base'; | ||
import { createBatchLoader } from '@core/dataloader/utils'; | ||
import { User } from '@domain/community/user/user.entity'; | ||
import { Organization } from '@domain/community/organization'; | ||
import { VirtualContributor } from '@domain/community/virtual-contributor/virtual.contributor.entity'; | ||
|
||
@Injectable() | ||
export class CommunityTypeLoaderCreator | ||
implements DataLoaderCreator<{ id: string; type: CommunityContributorType }> | ||
{ | ||
constructor(@InjectEntityManager() private manager: EntityManager) {} | ||
|
||
create() { | ||
return createBatchLoader( | ||
this.constructor.name, | ||
'CommunityContributorType', | ||
this.communityTypeInBatch | ||
); | ||
} | ||
|
||
private async communityTypeInBatch( | ||
keys: ReadonlyArray<string> | ||
): Promise<{ id: string; type: CommunityContributorType }[]> { | ||
const result = await this.manager | ||
.createQueryBuilder() | ||
.select('user.id') | ||
.from(User, 'user') | ||
.addSelect('organization.id') | ||
.addFrom(Organization, 'organization') | ||
.addSelect('vc.id') | ||
.addFrom(VirtualContributor, 'vc') | ||
.where('user.id IN (:...ids)', { ids: keys }) | ||
.orWhere('organization.id IN (:...ids)', { ids: keys }) | ||
.orWhere('vc.id IN (:...ids)', { ids: keys }) | ||
.getRawMany<User | Organization | VirtualContributor>(); | ||
|
||
return result.map(item => { | ||
if (item instanceof User) { | ||
return { id: item.id, type: CommunityContributorType.USER }; | ||
} | ||
if (item instanceof Organization) { | ||
return { id: item.id, type: CommunityContributorType.ORGANIZATION }; | ||
} | ||
return { id: item.id, type: CommunityContributorType.VIRTUAL }; | ||
}); | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
...ore/dataloader/creators/loader.creators/in-app-notification/contributor.loader.creator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { EntityManager, In } from 'typeorm'; | ||
import { Injectable } from '@nestjs/common'; | ||
import { InjectEntityManager } from '@nestjs/typeorm'; | ||
import { DataLoaderCreator } from '@core/dataloader/creators/base'; | ||
import { createBatchLoader } from '@core/dataloader/utils'; | ||
import { ILoader } from '@core/dataloader/loader.interface'; | ||
import { IContributor } from '@domain/community/contributor/contributor.interface'; | ||
import { User } from '@domain/community/user/user.entity'; | ||
import { Organization } from '@domain/community/organization'; | ||
import { VirtualContributor } from '@domain/community/virtual-contributor/virtual.contributor.entity'; | ||
import { IContributorBase } from '@domain/community/contributor'; | ||
|
||
@Injectable() | ||
export class ContributorLoaderCreator | ||
implements DataLoaderCreator<IContributorBase> | ||
{ | ||
constructor(@InjectEntityManager() private manager: EntityManager) {} | ||
|
||
public create(): ILoader<IContributor> { | ||
return createBatchLoader( | ||
this.constructor.name, | ||
'Contributor', | ||
this.contributorsInBatch | ||
); | ||
} | ||
|
||
private contributorsInBatch = async ( | ||
keys: ReadonlyArray<string> | ||
): Promise<(User | Organization | VirtualContributor)[]> => { | ||
// do when we actually need all contributors | ||
// const a = await this.manager.query(` | ||
// SELECT \`user\`.\`id\`, 'User' AS \`type\` | ||
// FROM \`user\` | ||
// WHERE \`user\`.\`id\` IN (${strKeys}) | ||
// | ||
// UNION | ||
// | ||
// SELECT \`vc\`.\`id\`, 'VirtualContributor' AS \`type\` | ||
// FROM \`virtual_contributor\` \`vc\` | ||
// WHERE \`vc\`.\`id\` IN (${strKeys}) | ||
// | ||
// UNION | ||
// | ||
// SELECT \`organization\`.\`id\`, 'Organization' AS \`type\` | ||
// FROM \`organization\` | ||
// WHERE \`organization\`.\`id\` IN (${strKeys}); | ||
// `); | ||
|
||
return this.manager.findBy(User, { id: In(keys) }); | ||
}; | ||
} |
25 changes: 25 additions & 0 deletions
25
src/core/dataloader/creators/loader.creators/in-app-notification/space.loader.creator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { EntityManager, In } from 'typeorm'; | ||
import { Injectable } from '@nestjs/common'; | ||
import { InjectEntityManager } from '@nestjs/typeorm'; | ||
import { DataLoaderCreator } from '@core/dataloader/creators/base'; | ||
import { createBatchLoader } from '@core/dataloader/utils'; | ||
import { ILoader } from '@core/dataloader/loader.interface'; | ||
import { ISpace } from '@domain/space/space/space.interface'; | ||
import { Space } from '@domain/space/space/space.entity'; | ||
|
||
@Injectable() | ||
export class SpaceLoaderCreator implements DataLoaderCreator<ISpace> { | ||
constructor(@InjectEntityManager() private manager: EntityManager) {} | ||
|
||
public create(): ILoader<ISpace> { | ||
return createBatchLoader( | ||
this.constructor.name, | ||
Space.name, | ||
this.spaceInBatch | ||
); | ||
} | ||
|
||
private spaceInBatch = (keys: ReadonlyArray<string>): Promise<Space[]> => { | ||
return this.manager.findBy(Space, { id: In(keys) }); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import DataLoader from 'dataloader'; | ||
import { EntityNotFoundException } from '@common/exceptions'; | ||
import { LogContext } from '@common/enums'; | ||
import { ILoader } from '../loader.interface'; | ||
import { sorOutputByKeys } from '@core/dataloader/utils/sort.output.by.keys'; | ||
|
||
export const createBatchLoader = <TResult extends { id: string }>( | ||
name: string, // for debugging purposes | ||
loadedTypeName: string, // for debugging purposes | ||
batchLoadFn: (keys: ReadonlyArray<string>) => Promise<TResult[]> | ||
): ILoader<TResult> => { | ||
// the data loader returns an array the MUST match the input length | ||
// the provided batch function does not necessarily complete this requirement | ||
// so we create a wrapper function that executes the batch function and ensure the output length | ||
// by either returning the original output (if the length matches) or filling the missing values with errors | ||
const loadAndEnsureOutputLengthAndOrder = async (keys: readonly string[]) => { | ||
const unsortedOutput = await batchLoadFn(keys); | ||
const sortedOutput = sorOutputByKeys(unsortedOutput, keys); | ||
if (sortedOutput.length == keys.length) { | ||
// length is ensured | ||
return sortedOutput; | ||
} | ||
// maps each returned result to its id | ||
const resultsById = new Map<string, TResult>( | ||
sortedOutput.map<[string, TResult]>(result => [result.id, result]) | ||
); | ||
// ensure the result length matches the input length | ||
return keys.map( | ||
key => resultsById.get(key) ?? resolveUnresolvedForKey(key) | ||
); | ||
}; | ||
// a function to resolve an unresolved entity for a given key (e.g. if not found, etc.) | ||
const resolveUnresolvedForKey = (key: string) => { | ||
return new EntityNotFoundException( | ||
`Could not find ${loadedTypeName} for the given key`, | ||
LogContext.DATA_LOADER, | ||
{ id: key } | ||
); | ||
}; | ||
|
||
return new DataLoader<string, TResult>( | ||
keys => loadAndEnsureOutputLengthAndOrder(keys), | ||
{ | ||
cache: true, | ||
name, | ||
} | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { sortBy } from 'lodash'; | ||
|
||
export const sorOutputByKeys = <T extends { id: string }>( | ||
output: T[], | ||
keys: readonly string[] | ||
) => { | ||
const orderMap = keys.reduce( | ||
(acc, key, index) => { | ||
acc[key] = index; | ||
return acc; | ||
}, | ||
{} as Record<string, number> | ||
); | ||
return sortBy(output, obj => orderMap[obj.id]); | ||
}; |
Oops, something went wrong.