Merge branch 'dev-1' into dev

This commit is contained in:
Wuesteon 2025-12-05 17:57:26 +01:00
commit d41d060bb3
1770 changed files with 168028 additions and 31031 deletions

View file

@ -0,0 +1,47 @@
import { Controller, Get, Post, Delete, Param, Query, UseGuards } from '@nestjs/common';
import { JwtAuthGuard, CurrentUser } from '@manacore/shared-nestjs-auth';
import type { CurrentUserData } from '@manacore/shared-nestjs-auth';
import { TrashService } from './trash.service';
@Controller('api/v1/trash')
@UseGuards(JwtAuthGuard)
export class TrashController {
constructor(private readonly trashService: TrashService) {}
@Get()
async findAll(@CurrentUser() user: CurrentUserData) {
return this.trashService.findAll(user.userId);
}
@Post(':id/restore')
async restore(
@CurrentUser() user: CurrentUserData,
@Param('id') id: string,
@Query('type') type: 'file' | 'folder'
) {
if (type === 'folder') {
return this.trashService.restoreFolder(user.userId, id);
}
return this.trashService.restoreFile(user.userId, id);
}
@Delete(':id')
async permanentlyDelete(
@CurrentUser() user: CurrentUserData,
@Param('id') id: string,
@Query('type') type: 'file' | 'folder'
) {
if (type === 'folder') {
await this.trashService.permanentlyDeleteFolder(user.userId, id);
} else {
await this.trashService.permanentlyDeleteFile(user.userId, id);
}
return { success: true };
}
@Delete()
async emptyTrash(@CurrentUser() user: CurrentUserData) {
await this.trashService.emptyTrash(user.userId);
return { success: true };
}
}

View file

@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { TrashController } from './trash.controller';
import { TrashService } from './trash.service';
@Module({
controllers: [TrashController],
providers: [TrashService],
exports: [TrashService],
})
export class TrashModule {}

View file

@ -0,0 +1,107 @@
import { Injectable, Inject, NotFoundException } from '@nestjs/common';
import { eq, and } from 'drizzle-orm';
import { DATABASE_CONNECTION } from '../db/database.module';
import { Database } from '../db/connection';
import { files, folders } from '../db/schema';
import type { File, Folder } from '../db/schema';
import { StorageService } from '../storage/storage.service';
@Injectable()
export class TrashService {
constructor(
@Inject(DATABASE_CONNECTION) private db: Database,
private storageService: StorageService
) {}
async findAll(userId: string): Promise<{ files: File[]; folders: Folder[] }> {
const trashedFiles = await this.db
.select()
.from(files)
.where(and(eq(files.userId, userId), eq(files.isDeleted, true)));
const trashedFolders = await this.db
.select()
.from(folders)
.where(and(eq(folders.userId, userId), eq(folders.isDeleted, true)));
return { files: trashedFiles, folders: trashedFolders };
}
async restoreFile(userId: string, id: string): Promise<File> {
const result = await this.db
.update(files)
.set({
isDeleted: false,
deletedAt: null,
updatedAt: new Date(),
})
.where(and(eq(files.id, id), eq(files.userId, userId)))
.returning();
if (result.length === 0) {
throw new NotFoundException('File not found in trash');
}
return result[0];
}
async restoreFolder(userId: string, id: string): Promise<Folder> {
const result = await this.db
.update(folders)
.set({
isDeleted: false,
deletedAt: null,
updatedAt: new Date(),
})
.where(and(eq(folders.id, id), eq(folders.userId, userId)))
.returning();
if (result.length === 0) {
throw new NotFoundException('Folder not found in trash');
}
return result[0];
}
async permanentlyDeleteFile(userId: string, id: string): Promise<void> {
const file = await this.db
.select()
.from(files)
.where(and(eq(files.id, id), eq(files.userId, userId), eq(files.isDeleted, true)));
if (file.length === 0) {
throw new NotFoundException('File not found in trash');
}
// Delete from S3
await this.storageService.deleteFile(file[0].storageKey);
// Delete from database
await this.db.delete(files).where(eq(files.id, id));
}
async permanentlyDeleteFolder(userId: string, id: string): Promise<void> {
await this.db
.delete(folders)
.where(and(eq(folders.id, id), eq(folders.userId, userId), eq(folders.isDeleted, true)));
}
async emptyTrash(userId: string): Promise<void> {
// Get all trashed files to delete from S3
const trashedFiles = await this.db
.select()
.from(files)
.where(and(eq(files.userId, userId), eq(files.isDeleted, true)));
// Delete from S3
for (const file of trashedFiles) {
await this.storageService.deleteFile(file.storageKey);
}
// Delete from database
await this.db.delete(files).where(and(eq(files.userId, userId), eq(files.isDeleted, true)));
await this.db
.delete(folders)
.where(and(eq(folders.userId, userId), eq(folders.isDeleted, true)));
}
}