Fix missing encoding in workspace-logo, members, person (#6510)
This commit is contained in:
@ -5,7 +5,7 @@ export const getImageAbsoluteURI = (imageUrl?: string | null) => {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (imageUrl?.startsWith('https:')) {
|
if (imageUrl?.startsWith('https:') || imageUrl?.startsWith('http:')) {
|
||||||
return imageUrl;
|
return imageUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,10 @@ import {
|
|||||||
} from 'src/engine/integrations/file-storage/interfaces/file-storage-exception';
|
} from 'src/engine/integrations/file-storage/interfaces/file-storage-exception';
|
||||||
|
|
||||||
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
||||||
import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity';
|
import {
|
||||||
|
Workspace,
|
||||||
|
WorkspaceActivationStatus,
|
||||||
|
} from 'src/engine/core-modules/workspace/workspace.entity';
|
||||||
import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service';
|
import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service';
|
||||||
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
import { DataSourceService } from 'src/engine/metadata-modules/data-source/data-source.service';
|
||||||
|
|
||||||
@ -52,9 +55,11 @@ export class UpdateFileFolderStructureCommand extends CommandRunner {
|
|||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const workspaceIds = options.workspaceId
|
const workspaceIds = options.workspaceId
|
||||||
? [options.workspaceId]
|
? [options.workspaceId]
|
||||||
: (await this.workspaceRepository.find()).map(
|
: (
|
||||||
(workspace) => workspace.id,
|
await this.workspaceRepository.find({
|
||||||
);
|
where: { activationStatus: WorkspaceActivationStatus.ACTIVE },
|
||||||
|
})
|
||||||
|
).map((workspace) => workspace.id);
|
||||||
|
|
||||||
if (!workspaceIds.length) {
|
if (!workspaceIds.length) {
|
||||||
this.logger.log(chalk.yellow('No workspace found'));
|
this.logger.log(chalk.yellow('No workspace found'));
|
||||||
|
|||||||
@ -1,41 +1,21 @@
|
|||||||
import { addMilliseconds } from 'date-fns';
|
import { QueryResultGetterHandlerInterface } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/interfaces/query-result-getter-handler.interface';
|
||||||
import ms from 'ms';
|
|
||||||
|
|
||||||
import { QueryResultGuetterHandlerInterface } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/interfaces/query-result-getter-handler.interface';
|
import { FileService } from 'src/engine/core-modules/file/services/file.service';
|
||||||
|
|
||||||
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
|
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
|
||||||
|
|
||||||
export class AttachmentQueryResultGetterHandler
|
export class AttachmentQueryResultGetterHandler
|
||||||
implements QueryResultGuetterHandlerInterface
|
implements QueryResultGetterHandlerInterface
|
||||||
{
|
{
|
||||||
constructor(
|
constructor(private readonly fileService: FileService) {}
|
||||||
private readonly tokenService: TokenService,
|
|
||||||
private readonly environmentService: EnvironmentService,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
async process(attachment: any, workspaceId: string): Promise<any> {
|
async handle(attachment: any, workspaceId: string): Promise<any> {
|
||||||
if (!attachment.id || !attachment?.fullPath) {
|
if (!attachment.id || !attachment?.fullPath) {
|
||||||
return attachment;
|
return attachment;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileTokenExpiresIn = this.environmentService.get(
|
const signedPayload = await this.fileService.encodeFileToken({
|
||||||
'FILE_TOKEN_EXPIRES_IN',
|
attachment_id: attachment.id,
|
||||||
);
|
workspace_id: workspaceId,
|
||||||
const secret = this.environmentService.get('FILE_TOKEN_SECRET');
|
});
|
||||||
|
|
||||||
const expirationDate = addMilliseconds(new Date(), ms(fileTokenExpiresIn));
|
|
||||||
|
|
||||||
const signedPayload = await this.tokenService.encodePayload(
|
|
||||||
{
|
|
||||||
expiration_date: expirationDate,
|
|
||||||
attachment_id: attachment.id,
|
|
||||||
workspace_id: workspaceId,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
secret,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...attachment,
|
...attachment,
|
||||||
|
|||||||
@ -0,0 +1,29 @@
|
|||||||
|
import { QueryResultGetterHandlerInterface } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/interfaces/query-result-getter-handler.interface';
|
||||||
|
|
||||||
|
import { FileService } from 'src/engine/core-modules/file/services/file.service';
|
||||||
|
import { PersonWorkspaceEntity } from 'src/modules/person/standard-objects/person.workspace-entity';
|
||||||
|
|
||||||
|
export class PersonQueryResultGetterHandler
|
||||||
|
implements QueryResultGetterHandlerInterface
|
||||||
|
{
|
||||||
|
constructor(private readonly fileService: FileService) {}
|
||||||
|
|
||||||
|
async handle(
|
||||||
|
person: PersonWorkspaceEntity,
|
||||||
|
workspaceId: string,
|
||||||
|
): Promise<any> {
|
||||||
|
if (!person.id || !person?.avatarUrl) {
|
||||||
|
return person;
|
||||||
|
}
|
||||||
|
|
||||||
|
const signedPayload = await this.fileService.encodeFileToken({
|
||||||
|
person_id: person.id,
|
||||||
|
workspace_id: workspaceId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...person,
|
||||||
|
avatarUrl: `${person.avatarUrl}?token=${signedPayload}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
import { QueryResultGetterHandlerInterface } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/interfaces/query-result-getter-handler.interface';
|
||||||
|
|
||||||
|
import { FileService } from 'src/engine/core-modules/file/services/file.service';
|
||||||
|
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||||
|
|
||||||
|
export class WorkspaceMemberQueryResultGetterHandler
|
||||||
|
implements QueryResultGetterHandlerInterface
|
||||||
|
{
|
||||||
|
constructor(private readonly fileService: FileService) {}
|
||||||
|
|
||||||
|
async handle(
|
||||||
|
workspaceMember: WorkspaceMemberWorkspaceEntity,
|
||||||
|
workspaceId: string,
|
||||||
|
): Promise<any> {
|
||||||
|
if (!workspaceMember.id || !workspaceMember?.avatarUrl) {
|
||||||
|
return workspaceMember;
|
||||||
|
}
|
||||||
|
|
||||||
|
const signedPayload = await this.fileService.encodeFileToken({
|
||||||
|
workspace_member_id: workspaceMember.id,
|
||||||
|
workspace_id: workspaceId,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
...workspaceMember,
|
||||||
|
avatarUrl: `${workspaceMember.avatarUrl}?token=${signedPayload}`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,3 +1,3 @@
|
|||||||
export interface QueryResultGuetterHandlerInterface {
|
export interface QueryResultGetterHandlerInterface {
|
||||||
process(result: any, workspaceId: string): Promise<any>;
|
handle(result: any, workspaceId: string): Promise<any>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,31 +1,28 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import { QueryResultGuetterHandlerInterface } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/interfaces/query-result-getter-handler.interface';
|
import { QueryResultGetterHandlerInterface } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/interfaces/query-result-getter-handler.interface';
|
||||||
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
|
import { ObjectMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/object-metadata.interface';
|
||||||
|
|
||||||
import { AttachmentQueryResultGetterHandler } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/handlers/attachment-query-result-getter.handler';
|
import { AttachmentQueryResultGetterHandler } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/handlers/attachment-query-result-getter.handler';
|
||||||
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
|
import { PersonQueryResultGetterHandler } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/handlers/person-query-result-getter.handler';
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
import { WorkspaceMemberQueryResultGetterHandler } from 'src/engine/api/graphql/workspace-query-runner/factories/query-result-getters/handlers/workspace-member-query-result-getter.handler';
|
||||||
|
import { FileService } from 'src/engine/core-modules/file/services/file.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class QueryResultGettersFactory {
|
export class QueryResultGettersFactory {
|
||||||
private handlers: Map<string, QueryResultGuetterHandlerInterface>;
|
private handlers: Map<string, QueryResultGetterHandlerInterface>;
|
||||||
|
|
||||||
constructor(
|
constructor(private readonly fileService: FileService) {
|
||||||
private readonly tokenService: TokenService,
|
|
||||||
private readonly environmentService: EnvironmentService,
|
|
||||||
) {
|
|
||||||
this.initializeHandlers();
|
this.initializeHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
private initializeHandlers() {
|
private initializeHandlers() {
|
||||||
this.handlers = new Map<string, QueryResultGuetterHandlerInterface>([
|
this.handlers = new Map<string, QueryResultGetterHandlerInterface>([
|
||||||
|
['attachment', new AttachmentQueryResultGetterHandler(this.fileService)],
|
||||||
|
['person', new PersonQueryResultGetterHandler(this.fileService)],
|
||||||
[
|
[
|
||||||
'attachment',
|
'workspaceMember',
|
||||||
new AttachmentQueryResultGetterHandler(
|
new WorkspaceMemberQueryResultGetterHandler(this.fileService),
|
||||||
this.tokenService,
|
|
||||||
this.environmentService,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
@ -43,7 +40,7 @@ export class QueryResultGettersFactory {
|
|||||||
edges: await Promise.all(
|
edges: await Promise.all(
|
||||||
result.edges.map(async (edge: any) => ({
|
result.edges.map(async (edge: any) => ({
|
||||||
...edge,
|
...edge,
|
||||||
node: await handler.process(edge.node, workspaceId),
|
node: await handler.handle(edge.node, workspaceId),
|
||||||
})),
|
})),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
@ -54,19 +51,19 @@ export class QueryResultGettersFactory {
|
|||||||
...result,
|
...result,
|
||||||
records: await Promise.all(
|
records: await Promise.all(
|
||||||
result.records.map(
|
result.records.map(
|
||||||
async (item: any) => await handler.process(item, workspaceId),
|
async (item: any) => await handler.handle(item, workspaceId),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return await handler.process(result, workspaceId);
|
return await handler.handle(result, workspaceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getHandler(objectType: string): QueryResultGuetterHandlerInterface {
|
private getHandler(objectType: string): QueryResultGetterHandlerInterface {
|
||||||
return (
|
return (
|
||||||
this.handlers.get(objectType) || {
|
this.handlers.get(objectType) || {
|
||||||
process: (result: any) => result,
|
handle: (result: any) => result,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,16 +1,17 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { WorkspaceQueryBuilderModule } from 'src/engine/api/graphql/workspace-query-builder/workspace-query-builder.module';
|
import { WorkspaceQueryBuilderModule } from 'src/engine/api/graphql/workspace-query-builder/workspace-query-builder.module';
|
||||||
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
|
||||||
import { WorkspaceQueryHookModule } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.module';
|
|
||||||
import { workspaceQueryRunnerFactories } from 'src/engine/api/graphql/workspace-query-runner/factories';
|
|
||||||
import { AuthModule } from 'src/engine/core-modules/auth/auth.module';
|
|
||||||
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
|
||||||
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
|
||||||
import { TelemetryListener } from 'src/engine/api/graphql/workspace-query-runner/listeners/telemetry.listener';
|
|
||||||
import { AnalyticsModule } from 'src/engine/core-modules/analytics/analytics.module';
|
|
||||||
import { RecordPositionBackfillCommand } from 'src/engine/api/graphql/workspace-query-runner/commands/0-20-record-position-backfill.command';
|
import { RecordPositionBackfillCommand } from 'src/engine/api/graphql/workspace-query-runner/commands/0-20-record-position-backfill.command';
|
||||||
|
import { workspaceQueryRunnerFactories } from 'src/engine/api/graphql/workspace-query-runner/factories';
|
||||||
|
import { TelemetryListener } from 'src/engine/api/graphql/workspace-query-runner/listeners/telemetry.listener';
|
||||||
|
import { WorkspaceQueryHookModule } from 'src/engine/api/graphql/workspace-query-runner/workspace-query-hook/workspace-query-hook.module';
|
||||||
|
import { AnalyticsModule } from 'src/engine/core-modules/analytics/analytics.module';
|
||||||
|
import { AuthModule } from 'src/engine/core-modules/auth/auth.module';
|
||||||
import { DuplicateModule } from 'src/engine/core-modules/duplicate/duplicate.module';
|
import { DuplicateModule } from 'src/engine/core-modules/duplicate/duplicate.module';
|
||||||
|
import { FileModule } from 'src/engine/core-modules/file/file.module';
|
||||||
|
import { ObjectMetadataRepositoryModule } from 'src/engine/object-metadata-repository/object-metadata-repository.module';
|
||||||
|
import { WorkspaceDataSourceModule } from 'src/engine/workspace-datasource/workspace-datasource.module';
|
||||||
|
import { WorkspaceMemberWorkspaceEntity } from 'src/modules/workspace-member/standard-objects/workspace-member.workspace-entity';
|
||||||
|
|
||||||
import { WorkspaceQueryRunnerService } from './workspace-query-runner.service';
|
import { WorkspaceQueryRunnerService } from './workspace-query-runner.service';
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ import { EntityEventsToDbListener } from './listeners/entity-events-to-db.listen
|
|||||||
ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]),
|
ObjectMetadataRepositoryModule.forFeature([WorkspaceMemberWorkspaceEntity]),
|
||||||
AnalyticsModule,
|
AnalyticsModule,
|
||||||
DuplicateModule,
|
DuplicateModule,
|
||||||
|
FileModule,
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
WorkspaceQueryRunnerService,
|
WorkspaceQueryRunnerService,
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { forwardRef, Module } from '@nestjs/common';
|
||||||
|
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
|
||||||
import { FilePathGuard } from 'src/engine/core-modules/file/guards/file-path-guard';
|
|
||||||
import { AuthModule } from 'src/engine/core-modules/auth/auth.module';
|
import { AuthModule } from 'src/engine/core-modules/auth/auth.module';
|
||||||
import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module';
|
import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module';
|
||||||
|
import { FilePathGuard } from 'src/engine/core-modules/file/guards/file-path-guard';
|
||||||
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||||
|
|
||||||
import { FileService } from './services/file.service';
|
|
||||||
import { FileController } from './controllers/file.controller';
|
import { FileController } from './controllers/file.controller';
|
||||||
|
import { FileService } from './services/file.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [FileUploadModule, AuthModule],
|
imports: [FileUploadModule, forwardRef(() => AuthModule)],
|
||||||
providers: [FileService, EnvironmentService, FilePathGuard],
|
providers: [FileService, EnvironmentService, FilePathGuard],
|
||||||
exports: [FileService],
|
exports: [FileService],
|
||||||
controllers: [FileController],
|
controllers: [FileController],
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
|
||||||
|
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
|
||||||
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||||
import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service';
|
import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service';
|
||||||
|
|
||||||
@ -20,6 +21,10 @@ describe('FileService', () => {
|
|||||||
provide: EnvironmentService,
|
provide: EnvironmentService,
|
||||||
useValue: {},
|
useValue: {},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: TokenService,
|
||||||
|
useValue: {},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
}).compile();
|
}).compile();
|
||||||
|
|
||||||
|
|||||||
@ -2,16 +2,25 @@ import { Injectable } from '@nestjs/common';
|
|||||||
|
|
||||||
import { Stream } from 'stream';
|
import { Stream } from 'stream';
|
||||||
|
|
||||||
|
import { addMilliseconds } from 'date-fns';
|
||||||
|
import ms from 'ms';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FileStorageException,
|
FileStorageException,
|
||||||
FileStorageExceptionCode,
|
FileStorageExceptionCode,
|
||||||
} from 'src/engine/integrations/file-storage/interfaces/file-storage-exception';
|
} from 'src/engine/integrations/file-storage/interfaces/file-storage-exception';
|
||||||
|
|
||||||
|
import { TokenService } from 'src/engine/core-modules/auth/services/token.service';
|
||||||
|
import { EnvironmentService } from 'src/engine/integrations/environment/environment.service';
|
||||||
import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service';
|
import { FileStorageService } from 'src/engine/integrations/file-storage/file-storage.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class FileService {
|
export class FileService {
|
||||||
constructor(private readonly fileStorageService: FileStorageService) {}
|
constructor(
|
||||||
|
private readonly fileStorageService: FileStorageService,
|
||||||
|
private readonly environmentService: EnvironmentService,
|
||||||
|
private readonly tokenService: TokenService,
|
||||||
|
) {}
|
||||||
|
|
||||||
async getFileStream(
|
async getFileStream(
|
||||||
folderPath: string,
|
folderPath: string,
|
||||||
@ -39,4 +48,25 @@ export class FileService {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async encodeFileToken(payloadToEncode: Record<string, any>) {
|
||||||
|
const fileTokenExpiresIn = this.environmentService.get(
|
||||||
|
'FILE_TOKEN_EXPIRES_IN',
|
||||||
|
);
|
||||||
|
const secret = this.environmentService.get('FILE_TOKEN_SECRET');
|
||||||
|
|
||||||
|
const expirationDate = addMilliseconds(new Date(), ms(fileTokenExpiresIn));
|
||||||
|
|
||||||
|
const signedPayload = await this.tokenService.encodePayload(
|
||||||
|
{
|
||||||
|
expiration_date: expirationDate,
|
||||||
|
...payloadToEncode,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
secret,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return signedPayload;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm';
|
|||||||
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
import { TypeORMModule } from 'src/database/typeorm/typeorm.module';
|
||||||
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
import { TypeORMService } from 'src/database/typeorm/typeorm.service';
|
||||||
import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module';
|
import { FileUploadModule } from 'src/engine/core-modules/file/file-upload/file-upload.module';
|
||||||
|
import { FileModule } from 'src/engine/core-modules/file/file.module';
|
||||||
import { KeyValuePair } from 'src/engine/core-modules/key-value-pair/key-value-pair.entity';
|
import { KeyValuePair } from 'src/engine/core-modules/key-value-pair/key-value-pair.entity';
|
||||||
import { OnboardingModule } from 'src/engine/core-modules/onboarding/onboarding.module';
|
import { OnboardingModule } from 'src/engine/core-modules/onboarding/onboarding.module';
|
||||||
import { UserVarsModule } from 'src/engine/core-modules/user/user-vars/user-vars.module';
|
import { UserVarsModule } from 'src/engine/core-modules/user/user-vars/user-vars.module';
|
||||||
@ -26,6 +27,7 @@ import { UserService } from './services/user.service';
|
|||||||
imports: [
|
imports: [
|
||||||
NestjsQueryTypeOrmModule.forFeature([User], 'core'),
|
NestjsQueryTypeOrmModule.forFeature([User], 'core'),
|
||||||
TypeORMModule,
|
TypeORMModule,
|
||||||
|
FileModule,
|
||||||
],
|
],
|
||||||
resolvers: userAutoResolverOpts,
|
resolvers: userAutoResolverOpts,
|
||||||
}),
|
}),
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.
|
|||||||
import { SupportDriver } from 'src/engine/integrations/environment/interfaces/support.interface';
|
import { SupportDriver } from 'src/engine/integrations/environment/interfaces/support.interface';
|
||||||
|
|
||||||
import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service';
|
import { FileUploadService } from 'src/engine/core-modules/file/file-upload/services/file-upload.service';
|
||||||
|
import { FileService } from 'src/engine/core-modules/file/services/file.service';
|
||||||
import { OnboardingStatus } from 'src/engine/core-modules/onboarding/enums/onboarding-status.enum';
|
import { OnboardingStatus } from 'src/engine/core-modules/onboarding/enums/onboarding-status.enum';
|
||||||
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
|
import { OnboardingService } from 'src/engine/core-modules/onboarding/onboarding.service';
|
||||||
import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-member.dto';
|
import { WorkspaceMember } from 'src/engine/core-modules/user/dtos/workspace-member.dto';
|
||||||
@ -55,6 +56,7 @@ export class UserResolver {
|
|||||||
private readonly onboardingService: OnboardingService,
|
private readonly onboardingService: OnboardingService,
|
||||||
private readonly loadServiceWithWorkspaceContext: LoadServiceWithWorkspaceContext,
|
private readonly loadServiceWithWorkspaceContext: LoadServiceWithWorkspaceContext,
|
||||||
private readonly userVarService: UserVarsService,
|
private readonly userVarService: UserVarsService,
|
||||||
|
private readonly fileService: FileService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@Query(() => User)
|
@Query(() => User)
|
||||||
@ -68,6 +70,20 @@ export class UserResolver {
|
|||||||
|
|
||||||
assert(user, 'User not found');
|
assert(user, 'User not found');
|
||||||
|
|
||||||
|
user.workspaces = await Promise.all(
|
||||||
|
user.workspaces.map(async (userWorkspace) => {
|
||||||
|
if (userWorkspace.workspace.logo) {
|
||||||
|
const workspaceLogoToken = await this.fileService.encodeFileToken({
|
||||||
|
workspace_id: userWorkspace.workspace.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
userWorkspace.workspace.logo = `${userWorkspace.workspace.logo}?token=${workspaceLogoToken}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return userWorkspace;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +115,18 @@ export class UserResolver {
|
|||||||
async workspaceMember(
|
async workspaceMember(
|
||||||
@Parent() user: User,
|
@Parent() user: User,
|
||||||
): Promise<WorkspaceMember | undefined> {
|
): Promise<WorkspaceMember | undefined> {
|
||||||
return this.userService.loadWorkspaceMember(user);
|
const workspaceMember = await this.userService.loadWorkspaceMember(user);
|
||||||
|
|
||||||
|
if (workspaceMember && workspaceMember.avatarUrl) {
|
||||||
|
const avatarUrlToken = await this.fileService.encodeFileToken({
|
||||||
|
workspace_member_id: workspaceMember.id,
|
||||||
|
workspace_id: user.defaultWorkspace.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
workspaceMember.avatarUrl = `${workspaceMember.avatarUrl}?token=${avatarUrlToken}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return workspaceMember;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ResolveField(() => String, {
|
@ResolveField(() => String, {
|
||||||
|
|||||||
Reference in New Issue
Block a user