add image delete api

This commit is contained in:
rubikscraft
2022-05-04 21:50:11 +02:00
parent 80b60595fe
commit 966954acc7
4 changed files with 101 additions and 16 deletions

View File

@@ -1,7 +1,7 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { AsyncFailable, Fail } from 'picsur-shared/dist/types'; import { AsyncFailable, Fail } from 'picsur-shared/dist/types';
import { Repository } from 'typeorm'; import { In, Repository } from 'typeorm';
import { EImageDerivativeBackend } from '../../models/entities/image-derivative.entity'; import { EImageDerivativeBackend } from '../../models/entities/image-derivative.entity';
import { EImageFileBackend } from '../../models/entities/image-file.entity'; import { EImageFileBackend } from '../../models/entities/image-file.entity';
import { EImageBackend } from '../../models/entities/image.entity'; import { EImageBackend } from '../../models/entities/image.entity';
@@ -33,10 +33,13 @@ export class ImageDBService {
return imageEntity; return imageEntity;
} }
public async findOne(id: string): AsyncFailable<EImageBackend> { public async findOne(
id: string,
userid: string | undefined,
): AsyncFailable<EImageBackend> {
try { try {
const found = await this.imageRepo.findOne({ const found = await this.imageRepo.findOne({
where: { id }, where: { id, user_id: userid },
}); });
if (!found) return Fail('Image not found'); if (!found) return Fail('Image not found');
@@ -49,7 +52,7 @@ export class ImageDBService {
public async findMany( public async findMany(
count: number, count: number,
page: number, page: number,
userid: string | false, userid: string | undefined,
): AsyncFailable<EImageBackend[]> { ): AsyncFailable<EImageBackend[]> {
if (count < 1 || page < 0) return Fail('Invalid page'); if (count < 1 || page < 0) return Fail('Invalid page');
if (count > 100) return Fail('Too many results'); if (count > 100) return Fail('Too many results');
@@ -59,7 +62,7 @@ export class ImageDBService {
skip: count * page, skip: count * page,
take: count, take: count,
where: { where: {
user_id: userid === false ? undefined : userid, user_id: userid,
}, },
}); });
@@ -70,15 +73,40 @@ export class ImageDBService {
} }
} }
public async delete(id: string): AsyncFailable<true> { public async findList(
ids: string[],
userid: string | undefined,
): AsyncFailable<EImageBackend[]> {
if (ids.length === 0) return [];
if (ids.length > 500) return Fail('Too many results');
try {
const found = await this.imageRepo.find({
where: {
id: In(ids),
user_id: userid,
},
});
if (found === undefined) return Fail('Images not found');
return found;
} catch (e) {
return Fail(e);
}
}
public async delete(ids: string[]): AsyncFailable<true> {
if (ids.length === 0) return true;
if (ids.length > 500) return Fail('Too many results');
try { try {
const derivativesResult = await this.imageDerivativeRepo.delete({ const derivativesResult = await this.imageDerivativeRepo.delete({
image_id: id, image_id: In(ids),
}); });
const filesResult = await this.imageFileRepo.delete({ const filesResult = await this.imageFileRepo.delete({
image_id: id, image_id: In(ids),
}); });
const result = await this.imageRepo.delete({ id }); const result = await this.imageRepo.delete({ id: In(ids) });
if ( if (
result.affected === 0 && result.affected === 0 &&

View File

@@ -33,18 +33,35 @@ export class ImageManagerService {
private readonly sysPref: SysPreferenceService, private readonly sysPref: SysPreferenceService,
) {} ) {}
public async findOne(id: string): AsyncFailable<EImageBackend> { public async findOne(
return await this.imagesService.findOne(id); id: string,
): AsyncFailable<EImageBackend> {
return await this.imagesService.findOne(id, undefined);
} }
public async findMany( public async findMany(
count: number, count: number,
page: number, page: number,
userid: string | false, userid: string | undefined,
): AsyncFailable<EImageBackend[]> { ): AsyncFailable<EImageBackend[]> {
return await this.imagesService.findMany(count, page, userid); return await this.imagesService.findMany(count, page, userid);
} }
public async deleteMany(
ids: string[],
userid: string | undefined,
): AsyncFailable<EImageBackend[]> {
const images = await this.imagesService.findList(ids, userid);
if (HasFailed(images)) return images;
const availableIds = images.map(image => image.id);
const deleteResult = await this.imagesService.delete(availableIds);
if (HasFailed(deleteResult)) return deleteResult;
return images;
}
public async upload( public async upload(
image: Buffer, image: Buffer,
userid: string, userid: string,

View File

@@ -1,4 +1,5 @@
import { import {
BadRequestException,
Body, Body,
Controller, Controller,
InternalServerErrorException, InternalServerErrorException,
@@ -6,6 +7,8 @@ import {
Post Post
} from '@nestjs/common'; } from '@nestjs/common';
import { import {
ImageDeleteRequest,
ImageDeleteResponse,
ImageListRequest, ImageListRequest,
ImageListResponse, ImageListResponse,
ImageUploadResponse ImageUploadResponse
@@ -61,7 +64,7 @@ export class ImageManageController {
const images = await this.imagesService.findMany( const images = await this.imagesService.findMany(
body.count, body.count,
body.page, body.page,
userid, body.user_id,
); );
if (HasFailed(images)) { if (HasFailed(images)) {
this.logger.warn(images.getReason()); this.logger.warn(images.getReason());
@@ -74,4 +77,26 @@ export class ImageManageController {
page: body.page, page: body.page,
}; };
} }
@Post('delete')
@Returns(ImageDeleteResponse)
async deleteImage(
@Body() body: ImageDeleteRequest,
@ReqUserID() userid: string,
@HasPermission(Permission.ImageAdmin) isImageAdmin: boolean,
): Promise<ImageDeleteResponse> {
const deletedImages = await this.imagesService.deleteMany(
body.ids,
isImageAdmin ? undefined : userid,
);
if (HasFailed(deletedImages)) {
this.logger.warn(deletedImages.getReason());
throw new BadRequestException('Could not delete images');
}
return {
images: deletedImages,
count: deletedImages.length,
};
}
} }

View File

@@ -16,9 +16,7 @@ export const ImageListRequestSchema = z.object({
page: IsPosInt(), page: IsPosInt(),
user_id: z.string().uuid().optional(), user_id: z.string().uuid().optional(),
}); });
export class ImageListRequest extends createZodDto( export class ImageListRequest extends createZodDto(ImageListRequestSchema) {}
ImageListRequestSchema,
) {}
export const ImageListResponseSchema = z.object({ export const ImageListResponseSchema = z.object({
images: z.array(EImageSchema), images: z.array(EImageSchema),
@@ -26,3 +24,20 @@ export const ImageListResponseSchema = z.object({
page: IsPosInt(), page: IsPosInt(),
}); });
export class ImageListResponse extends createZodDto(ImageListResponseSchema) {} export class ImageListResponse extends createZodDto(ImageListResponseSchema) {}
// Image Delete
export const ImageDeleteRequestSchema = z.object({
ids: z.array(z.string().uuid()),
});
export class ImageDeleteRequest extends createZodDto(
ImageDeleteRequestSchema,
) {}
export const ImageDeleteResponseSchema = z.object({
images: z.array(EImageSchema),
count: IsPosInt(),
});
export class ImageDeleteResponse extends createZodDto(
ImageDeleteResponseSchema,
) {}