Move defaultAvatarUrl on userWorkspace + migration command (#12100)
closes https://github.com/twentyhq/core-team-issues/issues/883
This commit is contained in:
@ -1,3 +1,4 @@
|
||||
import { HttpModule } from '@nestjs/axios';
|
||||
import { Module } from '@nestjs/common';
|
||||
|
||||
import { FileUploadResolver } from 'src/engine/core-modules/file/file-upload/resolvers/file-upload.resolver';
|
||||
@ -5,7 +6,7 @@ import { FileUploadService } from 'src/engine/core-modules/file/file-upload/serv
|
||||
import { FileModule } from 'src/engine/core-modules/file/file.module';
|
||||
|
||||
@Module({
|
||||
imports: [FileModule],
|
||||
imports: [FileModule, HttpModule],
|
||||
providers: [FileUploadService, FileUploadResolver],
|
||||
exports: [FileUploadService, FileUploadResolver],
|
||||
})
|
||||
|
||||
@ -1,22 +1,25 @@
|
||||
import { HttpService } from '@nestjs/axios';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import DOMPurify from 'dompurify';
|
||||
import FileType from 'file-type';
|
||||
import { JSDOM } from 'jsdom';
|
||||
import sharp from 'sharp';
|
||||
import { v4 as uuidV4 } from 'uuid';
|
||||
import { v4 as uuidV4, v4 } from 'uuid';
|
||||
|
||||
import { FileFolder } from 'src/engine/core-modules/file/interfaces/file-folder.interface';
|
||||
|
||||
import { settings } from 'src/engine/constants/settings';
|
||||
import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service';
|
||||
import { FileService } from 'src/engine/core-modules/file/services/file.service';
|
||||
import { getCropSize } from 'src/utils/image';
|
||||
import { getCropSize, getImageBufferFromUrl } from 'src/utils/image';
|
||||
|
||||
@Injectable()
|
||||
export class FileUploadService {
|
||||
constructor(
|
||||
private readonly fileStorage: FileStorageService,
|
||||
private readonly fileService: FileService,
|
||||
private readonly httpService: HttpService,
|
||||
) {}
|
||||
|
||||
private async _uploadFile({
|
||||
@ -93,6 +96,31 @@ export class FileUploadService {
|
||||
};
|
||||
}
|
||||
|
||||
async uploadImageFromUrl({
|
||||
imageUrl,
|
||||
fileFolder,
|
||||
workspaceId,
|
||||
}: {
|
||||
imageUrl: string;
|
||||
fileFolder: FileFolder;
|
||||
workspaceId: string;
|
||||
}) {
|
||||
const buffer = await getImageBufferFromUrl(
|
||||
imageUrl,
|
||||
this.httpService.axiosRef,
|
||||
);
|
||||
|
||||
const type = await FileType.fromBuffer(buffer);
|
||||
|
||||
return await this.uploadImage({
|
||||
file: buffer,
|
||||
filename: `${v4()}.${type?.ext}`,
|
||||
mimeType: type?.mime,
|
||||
fileFolder,
|
||||
workspaceId,
|
||||
});
|
||||
}
|
||||
|
||||
async uploadImage({
|
||||
file,
|
||||
filename,
|
||||
|
||||
@ -6,8 +6,13 @@ import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twent
|
||||
|
||||
import { FileService } from './file.service';
|
||||
|
||||
jest.mock('uuid', () => ({
|
||||
v4: jest.fn(() => 'mocked-uuid'),
|
||||
}));
|
||||
|
||||
describe('FileService', () => {
|
||||
let service: FileService;
|
||||
let fileStorageService: FileStorageService;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
@ -15,7 +20,9 @@ describe('FileService', () => {
|
||||
FileService,
|
||||
{
|
||||
provide: FileStorageService,
|
||||
useValue: {},
|
||||
useValue: {
|
||||
copy: jest.fn(),
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: TwentyConfigService,
|
||||
@ -29,9 +36,35 @@ describe('FileService', () => {
|
||||
}).compile();
|
||||
|
||||
service = module.get<FileService>(FileService);
|
||||
fileStorageService = module.get<FileStorageService>(FileStorageService);
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(service).toBeDefined();
|
||||
});
|
||||
|
||||
it('copyFileFromWorkspaceToWorkspace - should copy a file to a new workspace', async () => {
|
||||
const result = await service.copyFileFromWorkspaceToWorkspace(
|
||||
'workspaceId',
|
||||
'path/to/file',
|
||||
'newWorkspaceId',
|
||||
);
|
||||
|
||||
expect(fileStorageService.copy).toHaveBeenCalledWith({
|
||||
from: {
|
||||
folderPath: 'workspace-workspaceId/path/to',
|
||||
filename: 'file',
|
||||
},
|
||||
to: {
|
||||
folderPath: 'workspace-newWorkspaceId/path/to',
|
||||
filename: 'mocked-uuid',
|
||||
},
|
||||
});
|
||||
|
||||
expect(result).toEqual([
|
||||
'workspace-newWorkspaceId',
|
||||
'path/to',
|
||||
'mocked-uuid',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { basename, dirname, extname } from 'path';
|
||||
import { Stream } from 'stream';
|
||||
|
||||
import { v4 as uuidV4 } from 'uuid';
|
||||
|
||||
import { FileStorageService } from 'src/engine/core-modules/file-storage/file-storage.service';
|
||||
import { JwtWrapperService } from 'src/engine/core-modules/jwt/services/jwt-wrapper.service';
|
||||
import { TwentyConfigService } from 'src/engine/core-modules/twenty-config/twenty-config.service';
|
||||
@ -74,4 +77,30 @@ export class FileService {
|
||||
folderPath: workspaceFolderPath,
|
||||
});
|
||||
}
|
||||
|
||||
async copyFileFromWorkspaceToWorkspace(
|
||||
fromWorkspaceId: string,
|
||||
fromPath: string,
|
||||
toWorkspaceId: string,
|
||||
) {
|
||||
const subFolder = dirname(fromPath);
|
||||
const fromWorkspaceFolderPath = `workspace-${fromWorkspaceId}`;
|
||||
const toWorkspaceFolderPath = `workspace-${toWorkspaceId}`;
|
||||
const fromFilename = basename(fromPath);
|
||||
|
||||
const toFilename = uuidV4() + extname(fromFilename);
|
||||
|
||||
await this.fileStorageService.copy({
|
||||
from: {
|
||||
folderPath: `${fromWorkspaceFolderPath}/${subFolder}`,
|
||||
filename: fromFilename,
|
||||
},
|
||||
to: {
|
||||
folderPath: `${toWorkspaceFolderPath}/${subFolder}`,
|
||||
filename: toFilename,
|
||||
},
|
||||
});
|
||||
|
||||
return [toWorkspaceFolderPath, subFolder, toFilename];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user