velody/backend/src/modules/assets/assets.service.ts

75 lines
1.8 KiB
TypeScript

import {
ForbiddenException,
Injectable,
NotFoundException,
} from '@nestjs/common';
import { stat } from 'node:fs/promises';
import { PrismaService } from '../../infrastructure/database/prisma.service';
import { LocalFilesystemStorageService } from '../storage/storage.service';
export interface AudioAssetDownload {
filePath: string;
contentLength: number;
}
@Injectable()
export class AssetsService {
constructor(
private readonly prismaService: PrismaService,
private readonly storageService: LocalFilesystemStorageService,
) {}
async getOwnedAudioAssetDownload(
assetId: string,
deviceId: string,
): Promise<AudioAssetDownload> {
const device = await this.prismaService.device.findUnique({
where: { id: deviceId },
select: {
userId: true,
},
});
if (!device) {
throw new NotFoundException('Device not found');
}
const asset = await this.prismaService.audioAsset.findUnique({
where: { id: assetId },
select: {
userId: true,
storageKey: true,
},
});
if (!asset) {
throw new NotFoundException('Audio asset not found');
}
if (asset.userId !== device.userId) {
throw new ForbiddenException('Audio asset does not belong to this device user.');
}
const filePath = this.storageService.resolve(asset.storageKey);
try {
const fileStats = await stat(filePath);
if (!fileStats.isFile()) {
throw new NotFoundException('Audio asset file not found');
}
return {
filePath,
contentLength: fileStats.size,
};
} catch (error) {
if (error instanceof NotFoundException) {
throw error;
}
throw new NotFoundException('Audio asset file not found');
}
}
}