refactor(server): upload config (#3252)

This commit is contained in:
Jason Rasmussen 2023-07-14 21:31:42 -04:00 committed by GitHub
parent 382341f550
commit 1064128fde
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 213 additions and 217 deletions

View file

@ -1,18 +1,21 @@
import { AssetType } from '@app/infra/entities';
import { BadRequestException } from '@nestjs/common';
import { BadRequestException, UnauthorizedException } from '@nestjs/common';
import {
assetEntityStub,
authStub,
IAccessRepositoryMock,
newAccessRepositoryMock,
newAssetRepositoryMock,
newCryptoRepositoryMock,
newStorageRepositoryMock,
} from '@test';
import { when } from 'jest-when';
import { Readable } from 'stream';
import { ICryptoRepository } from '../crypto';
import { mimeTypes } from '../domain.constant';
import { IStorageRepository } from '../storage';
import { AssetStats, IAssetRepository } from './asset.repository';
import { AssetService } from './asset.service';
import { AssetService, UploadFieldName } from './asset.service';
import { AssetStatsResponseDto, DownloadResponseDto } from './dto';
import { mapAsset } from './response-dto';
@ -39,10 +42,62 @@ const statResponse: AssetStatsResponseDto = {
total: 33,
};
const uploadFile = {
nullAuth: {
authUser: null,
fieldName: UploadFieldName.ASSET_DATA,
file: {
checksum: Buffer.from('checksum', 'utf8'),
originalPath: 'upload/admin/image.jpeg',
originalName: 'image.jpeg',
},
},
filename: (fieldName: UploadFieldName, filename: string) => {
return {
authUser: authStub.admin,
fieldName,
file: {
mimeType: 'image/jpeg',
checksum: Buffer.from('checksum', 'utf8'),
originalPath: `upload/admin/${filename}`,
originalName: filename,
},
};
},
};
const uploadTests = [
{
label: 'asset',
fieldName: UploadFieldName.ASSET_DATA,
filetypes: Object.keys({ ...mimeTypes.image, ...mimeTypes.video }),
invalid: ['.xml', '.html'],
},
{
label: 'live photo',
fieldName: UploadFieldName.LIVE_PHOTO_DATA,
filetypes: Object.keys(mimeTypes.video),
invalid: ['.xml', '.html', '.jpg', '.jpeg'],
},
{
label: 'sidecar',
fieldName: UploadFieldName.SIDECAR_DATA,
filetypes: Object.keys(mimeTypes.sidecar),
invalid: ['.xml', '.html', '.jpg', '.jpeg', '.mov', '.mp4'],
},
{
label: 'profile',
fieldName: UploadFieldName.PROFILE_DATA,
filetypes: Object.keys(mimeTypes.profile),
invalid: ['.xml', '.html', '.cr2', '.arf', '.mov', '.mp4'],
},
];
describe(AssetService.name, () => {
let sut: AssetService;
let accessMock: IAccessRepositoryMock;
let assetMock: jest.Mocked<IAssetRepository>;
let cryptoMock: jest.Mocked<ICryptoRepository>;
let storageMock: jest.Mocked<IStorageRepository>;
it('should work', () => {
@ -52,8 +107,83 @@ describe(AssetService.name, () => {
beforeEach(async () => {
accessMock = newAccessRepositoryMock();
assetMock = newAssetRepositoryMock();
cryptoMock = newCryptoRepositoryMock();
storageMock = newStorageRepositoryMock();
sut = new AssetService(accessMock, assetMock, storageMock);
sut = new AssetService(accessMock, assetMock, cryptoMock, storageMock);
});
describe('canUpload', () => {
it('should require an authenticated user', () => {
expect(() => sut.canUploadFile(uploadFile.nullAuth)).toThrowError(UnauthorizedException);
});
for (const { fieldName, filetypes, invalid } of uploadTests) {
describe(`${fieldName}`, () => {
for (const filetype of filetypes) {
it(`should accept ${filetype}`, () => {
expect(sut.canUploadFile(uploadFile.filename(fieldName, `asset${filetype}`))).toEqual(true);
});
}
for (const filetype of invalid) {
it(`should reject ${filetype}`, () => {
expect(() => sut.canUploadFile(uploadFile.filename(fieldName, `asset${filetype}`))).toThrowError(
BadRequestException,
);
});
}
});
}
});
describe('getUploadFilename', () => {
it('should require authentication', () => {
expect(() => sut.getUploadFilename(uploadFile.nullAuth)).toThrowError(UnauthorizedException);
});
it('should be the original extension for asset upload', () => {
expect(sut.getUploadFilename(uploadFile.filename(UploadFieldName.ASSET_DATA, 'image.jpg'))).toEqual(
'random-uuid.jpg',
);
});
it('should be the mov extension for live photo upload', () => {
expect(sut.getUploadFilename(uploadFile.filename(UploadFieldName.LIVE_PHOTO_DATA, 'image.mp4'))).toEqual(
'random-uuid.mov',
);
});
it('should be the xmp extension for sidecar upload', () => {
expect(sut.getUploadFilename(uploadFile.filename(UploadFieldName.SIDECAR_DATA, 'image.html'))).toEqual(
'random-uuid.xmp',
);
});
it('should be the original extension for profile upload', () => {
expect(sut.getUploadFilename(uploadFile.filename(UploadFieldName.PROFILE_DATA, 'image.jpg'))).toEqual(
'random-uuid.jpg',
);
});
});
describe('getUploadFolder', () => {
it('should require authentication', () => {
expect(() => sut.getUploadFolder(uploadFile.nullAuth)).toThrowError(UnauthorizedException);
});
it('should return profile for profile uploads', () => {
expect(sut.getUploadFolder(uploadFile.filename(UploadFieldName.PROFILE_DATA, 'image.jpg'))).toEqual(
'upload/profile/admin_id',
);
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/profile/admin_id');
});
it('should return upload for everything else', () => {
expect(sut.getUploadFolder(uploadFile.filename(UploadFieldName.ASSET_DATA, 'image.jpg'))).toEqual(
'upload/upload/admin_id',
);
expect(storageMock.mkdirSync).toHaveBeenCalledWith('upload/upload/admin_id');
});
});
describe('getMapMarkers', () => {