mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-23 10:06:41 +02:00
Merge branch 'dev-1' into dev
This commit is contained in:
commit
d41d060bb3
1770 changed files with 168028 additions and 31031 deletions
|
|
@ -0,0 +1,55 @@
|
|||
import { Controller, Get, Post, Delete, Body, Param, UseGuards } from '@nestjs/common';
|
||||
import { JwtAuthGuard, CurrentUser } from '@manacore/shared-nestjs-auth';
|
||||
import type { CurrentUserData } from '@manacore/shared-nestjs-auth';
|
||||
import { ShareService } from './share.service';
|
||||
|
||||
@Controller('api/v1/shares')
|
||||
export class ShareController {
|
||||
constructor(private readonly shareService: ShareService) {}
|
||||
|
||||
@Get()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
async findAll(@CurrentUser() user: CurrentUserData) {
|
||||
return this.shareService.findAll(user.userId);
|
||||
}
|
||||
|
||||
@Get(':token')
|
||||
async findByToken(@Param('token') token: string) {
|
||||
return this.shareService.findByToken(token);
|
||||
}
|
||||
|
||||
@Post()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
async create(
|
||||
@CurrentUser() user: CurrentUserData,
|
||||
@Body()
|
||||
dto: {
|
||||
fileId?: string;
|
||||
folderId?: string;
|
||||
accessLevel?: 'view' | 'edit' | 'download';
|
||||
password?: string;
|
||||
maxDownloads?: number;
|
||||
expiresInDays?: number;
|
||||
}
|
||||
) {
|
||||
const expiresAt = dto.expiresInDays
|
||||
? new Date(Date.now() + dto.expiresInDays * 24 * 60 * 60 * 1000)
|
||||
: undefined;
|
||||
|
||||
return this.shareService.create(user.userId, {
|
||||
fileId: dto.fileId,
|
||||
folderId: dto.folderId,
|
||||
accessLevel: dto.accessLevel,
|
||||
password: dto.password,
|
||||
maxDownloads: dto.maxDownloads,
|
||||
expiresAt,
|
||||
});
|
||||
}
|
||||
|
||||
@Delete(':id')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
async delete(@CurrentUser() user: CurrentUserData, @Param('id') id: string) {
|
||||
await this.shareService.delete(user.userId, id);
|
||||
return { success: true };
|
||||
}
|
||||
}
|
||||
10
apps-archived/storage/apps/backend/src/share/share.module.ts
Normal file
10
apps-archived/storage/apps/backend/src/share/share.module.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { ShareController } from './share.controller';
|
||||
import { ShareService } from './share.service';
|
||||
|
||||
@Module({
|
||||
controllers: [ShareController],
|
||||
providers: [ShareService],
|
||||
exports: [ShareService],
|
||||
})
|
||||
export class ShareModule {}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
import { Injectable, Inject, NotFoundException } from '@nestjs/common';
|
||||
import { eq, and } from 'drizzle-orm';
|
||||
import { randomBytes } from 'crypto';
|
||||
import { DATABASE_CONNECTION } from '../db/database.module';
|
||||
import { Database } from '../db/connection';
|
||||
import { shares } from '../db/schema';
|
||||
import type { Share, NewShare } from '../db/schema';
|
||||
|
||||
@Injectable()
|
||||
export class ShareService {
|
||||
constructor(@Inject(DATABASE_CONNECTION) private db: Database) {}
|
||||
|
||||
async findAll(userId: string): Promise<Share[]> {
|
||||
return this.db
|
||||
.select()
|
||||
.from(shares)
|
||||
.where(and(eq(shares.userId, userId), eq(shares.isActive, true)));
|
||||
}
|
||||
|
||||
async findByToken(token: string): Promise<Share> {
|
||||
const result = await this.db
|
||||
.select()
|
||||
.from(shares)
|
||||
.where(and(eq(shares.shareToken, token), eq(shares.isActive, true)));
|
||||
|
||||
if (result.length === 0) {
|
||||
throw new NotFoundException('Share not found');
|
||||
}
|
||||
|
||||
const share = result[0];
|
||||
|
||||
// Check expiration
|
||||
if (share.expiresAt && new Date() > share.expiresAt) {
|
||||
throw new NotFoundException('Share link has expired');
|
||||
}
|
||||
|
||||
// Check download limit
|
||||
if (share.maxDownloads && share.downloadCount >= share.maxDownloads) {
|
||||
throw new NotFoundException('Share link download limit reached');
|
||||
}
|
||||
|
||||
return share;
|
||||
}
|
||||
|
||||
async create(
|
||||
userId: string,
|
||||
data: {
|
||||
fileId?: string;
|
||||
folderId?: string;
|
||||
accessLevel?: 'view' | 'edit' | 'download';
|
||||
password?: string;
|
||||
maxDownloads?: number;
|
||||
expiresAt?: Date;
|
||||
}
|
||||
): Promise<Share> {
|
||||
const shareToken = randomBytes(32).toString('hex');
|
||||
const shareType = data.fileId ? 'file' : 'folder';
|
||||
|
||||
const newShare: NewShare = {
|
||||
userId,
|
||||
fileId: data.fileId,
|
||||
folderId: data.folderId,
|
||||
shareType,
|
||||
shareToken,
|
||||
accessLevel: data.accessLevel || 'view',
|
||||
password: data.password, // Should be hashed in production
|
||||
maxDownloads: data.maxDownloads,
|
||||
expiresAt: data.expiresAt,
|
||||
};
|
||||
|
||||
const result = await this.db.insert(shares).values(newShare).returning();
|
||||
return result[0];
|
||||
}
|
||||
|
||||
async delete(userId: string, id: string): Promise<void> {
|
||||
await this.db
|
||||
.update(shares)
|
||||
.set({ isActive: false })
|
||||
.where(and(eq(shares.id, id), eq(shares.userId, userId)));
|
||||
}
|
||||
|
||||
async incrementDownloadCount(id: string): Promise<void> {
|
||||
const share = await this.db.select().from(shares).where(eq(shares.id, id));
|
||||
if (share.length > 0) {
|
||||
await this.db
|
||||
.update(shares)
|
||||
.set({
|
||||
downloadCount: share[0].downloadCount + 1,
|
||||
lastAccessedAt: new Date(),
|
||||
})
|
||||
.where(eq(shares.id, id));
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue