diff --git a/apps/server/package.json b/apps/server/package.json index 738b7e0..5fac39f 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -39,12 +39,12 @@ "exceljs": "^4.4.0", "ioredis": "^5.4.1", "mime-types": "^2.1.35", + "minio": "^8.0.1", "reflect-metadata": "^0.2.0", "rxjs": "^7.8.1", "socket.io": "^4.7.5", "superjson-cjs": "^2.2.3", - "tus-js-client": "^4.1.0", - "zod": "^3.23.8" + "tus-js-client": "^4.1.0" }, "devDependencies": { "@nestjs/cli": "^10.0.0", diff --git a/apps/server/src/app.module.ts b/apps/server/src/app.module.ts index 0212e07..0a10d11 100644 --- a/apps/server/src/app.module.ts +++ b/apps/server/src/app.module.ts @@ -12,12 +12,13 @@ import { ConfigService } from '@nestjs/config'; import { TasksModule } from './tasks/tasks.module'; import { JwtModule } from '@nestjs/jwt'; import { env } from './env'; +import { MinioModule } from './minio/minio.module'; @Module({ imports: [ScheduleModule.forRoot(), JwtModule.register({ global: true, secret: env.JWT_SECRET - }), TrpcModule, RedisModule, QueueModule, TransformModule, AuthModule, TasksModule], + }), TrpcModule, RedisModule, QueueModule, TransformModule, AuthModule, TasksModule, MinioModule], providers: [RedisService, SocketGateway, ConfigService], }) export class AppModule { } diff --git a/apps/server/src/auth/auth.controller.ts b/apps/server/src/auth/auth.controller.ts index 99270e7..c945af8 100644 --- a/apps/server/src/auth/auth.controller.ts +++ b/apps/server/src/auth/auth.controller.ts @@ -1,10 +1,8 @@ import { Controller, Post, Body, UseGuards, Get, Req } from '@nestjs/common'; import { AuthService } from './auth.service'; import { AuthSchema, JwtPayload } from '@nicestack/common'; - -import { z } from 'zod'; +import { z } from '@nicestack/common'; import { AuthGuard } from './auth.guard'; - @Controller('auth') export class AuthController { constructor(private readonly authService: AuthService) { } diff --git a/apps/server/src/init/init.module.ts b/apps/server/src/init/init.module.ts index ad6d316..e51a559 100644 --- a/apps/server/src/init/init.module.ts +++ b/apps/server/src/init/init.module.ts @@ -1,9 +1,10 @@ import { Module } from '@nestjs/common'; import { InitService } from './init.service'; import { AuthModule } from '@server/auth/auth.module'; +import { MinioModule } from '@server/minio/minio.module'; @Module({ - imports: [AuthModule], + imports: [AuthModule, MinioModule], providers: [InitService], exports: [InitService] }) diff --git a/apps/server/src/init/init.service.ts b/apps/server/src/init/init.service.ts index 2009c1c..c08701b 100644 --- a/apps/server/src/init/init.service.ts +++ b/apps/server/src/init/init.service.ts @@ -1,11 +1,12 @@ import { Injectable, Logger } from '@nestjs/common'; import { db, InitRoles, InitTaxonomies, ObjectType } from "@nicestack/common"; import { AuthService } from '@server/auth/auth.service'; +import { MinioService } from '@server/minio/minio.service'; @Injectable() export class InitService { private readonly logger = new Logger(InitService.name); - constructor(private readonly authService: AuthService) { } + constructor(private readonly authService: AuthService, private readonly minioService: MinioService) { } private async createRoles() { this.logger.log('Checking existing system roles'); for (const role of InitRoles) { @@ -41,7 +42,9 @@ export class InitService { } } } - + private async createBucket() { + await this.minioService.createBucket('app') + } private async createRoot() { this.logger.log('Checking for root account'); const rootAccountExists = await db.staff.findFirst({ @@ -91,5 +94,8 @@ export class InitService { this.logger.log('Initializing taxonomies'); await this.createTaxonomy(); + + this.logger.log('Initialize minio') + await this.createBucket() } } diff --git a/apps/server/src/minio/minio.module.ts b/apps/server/src/minio/minio.module.ts new file mode 100644 index 0000000..bce8484 --- /dev/null +++ b/apps/server/src/minio/minio.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { MinioService } from './minio.service'; + +@Module({ + providers: [MinioService], + exports: [MinioService] +}) +export class MinioModule {} diff --git a/apps/server/src/minio/minio.service.spec.ts b/apps/server/src/minio/minio.service.spec.ts new file mode 100644 index 0000000..8cc5a96 --- /dev/null +++ b/apps/server/src/minio/minio.service.spec.ts @@ -0,0 +1,18 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { MinioService } from './minio.service'; + +describe('MinioService', () => { + let service: MinioService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [MinioService], + }).compile(); + + service = module.get(MinioService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/apps/server/src/minio/minio.service.ts b/apps/server/src/minio/minio.service.ts new file mode 100644 index 0000000..4751298 --- /dev/null +++ b/apps/server/src/minio/minio.service.ts @@ -0,0 +1,26 @@ +import { Injectable, Logger } from '@nestjs/common'; +import * as Minio from 'minio'; + +@Injectable() +export class MinioService { + private readonly logger = new Logger(MinioService.name) + private readonly minioClient: Minio.Client; + constructor() { + this.minioClient = new Minio.Client({ + endPoint: 'localhost', + port: 9000, + useSSL: false, + accessKey: process.env.MINIO_ACCESS_KEY || 'minioadmin', + secretKey: process.env.MINIO_SECRET_KEY || 'minioadmin' + }); + } + async createBucket(bucketName: string): Promise { + const exists = await this.minioClient.bucketExists(bucketName); + if (!exists) { + await this.minioClient.makeBucket(bucketName, ''); + this.logger.log(`Bucket ${bucketName} created successfully.`); + } else { + this.logger.log(`Bucket ${bucketName} already exists.`); + } + } +}