Skip to content

Commit

Permalink
feat: implement File Upload
Browse files Browse the repository at this point in the history
- FINALLLLYYY!!!!!!!!!!
  • Loading branch information
HarshPatel5940 committed Oct 23, 2023
1 parent d2bf1c7 commit fd1bfce
Show file tree
Hide file tree
Showing 13 changed files with 1,563 additions and 1,304 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"@nestjs/jwt": "^10.1.1",
"@nestjs/platform-express": "^10.2.5",
"@prisma/client": "^5.3.1",
"@supabase/supabase-js": "^2.38.2",
"argon2": "^0.31.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
Expand All @@ -39,6 +40,7 @@
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
"slugify": "^1.6.6",
"tus-js-client": "^3.1.1",
"zod": "^3.22.3"
},
"devDependencies": {
Expand Down
2,608 changes: 1,437 additions & 1,171 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

73 changes: 0 additions & 73 deletions prisma/migrations/20230824075639_add_isdeleted/migration.sql

This file was deleted.

3 changes: 0 additions & 3 deletions prisma/migrations/migration_lock.toml

This file was deleted.

5 changes: 3 additions & 2 deletions prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ generator client {
}

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}

model User {
Expand Down
19 changes: 14 additions & 5 deletions src/api/project/project.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import {
Patch,
Post,
UploadedFile,
UseInterceptors,
UsePipes,
} from "@nestjs/common";
import { FileInterceptor } from "@nestjs/platform-express";

import { Express } from "express";
import { Multer } from "multer";

import {
projectAccessDto,
Expand All @@ -26,7 +27,11 @@ import {
ProjectDataDto,
projectDataSchema,

Check failure on line 28 in src/api/project/project.controller.ts

View workflow job for this annotation

GitHub Actions / lint-and-build

'projectDataSchema' is defined but never used
} from "../../shared/dto";
import { AuthRole, Roles } from "../../shared/guards/auth.decorator";
import {
AuthRole,
PublicRoute,
Roles,
} from "../../shared/guards/auth.decorator";
import { ZodValidationPipe } from "../../shared/pipes/zodPipe";
import { ProjectService } from "./project.service";

Expand Down Expand Up @@ -107,15 +112,19 @@ export class ProjectController {

@AuthRole(Roles.Verified)
@Post("/:slug/data/new")
@UsePipes(new ZodValidationPipe(projectDataSchema))
@PublicRoute()
@UseInterceptors(FileInterceptor("image"))
// TODO: Fix this pipe cause it will be receiving stuff in the form of multipart body form
// @UsePipes(new ZodValidationPipe(projectDataSchema))
CreateProjectData(
@Body() dto: ProjectDataDto,
@Param("slug") slug: string,
@UploadedFile(
new ParseFilePipe({
validators: [
new MaxFileSizeValidator({ maxSize: 1000 }),
new FileTypeValidator({ fileType: "image/jpeg" }),
new FileTypeValidator({
fileType: /image\/(jpeg|png|jpg)/,
}),
],
}),
)
Expand Down
3 changes: 2 additions & 1 deletion src/api/project/project.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { APP_GUARD } from "@nestjs/core";
import { JwtService } from "@nestjs/jwt";
import { PasswordService } from "src/api/auth/pwd.service";
import { AuthGuard } from "src/shared/guards/auth.guard";
import { SupabaseService } from "../../supabase/supabase.service";
import { ProjectController } from "./project.controller";
import { ProjectService } from "./project.service";

Expand All @@ -12,11 +13,11 @@ import { ProjectService } from "./project.service";
controllers: [ProjectController],
providers: [
ProjectService,
SupabaseService,
// ? The Below Are dependencies of the AuthGuard
JwtService,
ConfigService,
PasswordService,
// TODO: Add AWS Service
{
provide: APP_GUARD,
useClass: AuthGuard,
Expand Down
52 changes: 25 additions & 27 deletions src/api/project/project.service.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
import { HttpException, HttpStatus, Injectable, Logger } from "@nestjs/common";
import { Express } from "express";
import { Multer } from "multer";

Check failure on line 3 in src/api/project/project.service.ts

View workflow job for this annotation

GitHub Actions / lint-and-build

'Multer' is defined but never used
import { PrismaService } from "src/prisma/prisma.service";
import {
projectAccessDto,
projectCreateDto,
ProjectDataDto,
} from "../../shared/dto";
import { SupabaseService } from "../../supabase/supabase.service";

@Injectable()
export class ProjectService {
constructor(private readonly prisma: PrismaService) {}
constructor(
private readonly prisma: PrismaService,
private readonly supabase: SupabaseService,
) {}

async GetProject(Slug: string) {
console.log(Slug);
Expand Down Expand Up @@ -62,14 +67,7 @@ export class ProjectService {
}

async DeleteProject(Slug: string) {
const PROJECT = await this.prisma.project.findUnique({
where: {
slug: `${Slug}`,
},
select: {
slug: true,
},
});
const PROJECT = await this.GetProject(Slug);

if (!PROJECT) {
throw new HttpException("Project Not Found", HttpStatus.NOT_FOUND);
Expand All @@ -78,33 +76,33 @@ export class ProjectService {
return await this.prisma.DeleteProject(Slug);
}

async UpdateProjectAccess(slug: string, dto: projectAccessDto) {
const PROJECT = await this.prisma.project.findUnique({
where: {
slug: `${slug}`,
},
select: {
slug: true,
},
});

async UpdateProjectAccess(Slug: string, dto: projectAccessDto) {
const PROJECT = await this.GetProject(Slug);
if (!PROJECT) {
throw new HttpException("Project Not Found", HttpStatus.NOT_FOUND);
}

return await this.prisma.UpdateProjectAccess(dto, slug);
return await this.prisma.UpdateProjectAccess(dto, Slug);
}

async AddProjectData(
slug: string,
dto: ProjectDataDto,
file: Express.Multer.File,
) {
console.log(slug, dto, file);

// TODO: Upload Project Data to S3
// this.aws.
// TODO: Add Project Data from prisma
// this.prisma.
console.log(slug, dto);

try {
const link = await this.supabase.uploadFile(file);
console.log("=>", link);
// TODO: Add Project Data from prisma
// this.prisma.
} catch (error) {
Logger.debug(error);
throw new HttpException(
"Something Went Wrong",
HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}
}
8 changes: 0 additions & 8 deletions src/aws/aws.module.ts

This file was deleted.

4 changes: 0 additions & 4 deletions src/aws/aws.service.ts

This file was deleted.

43 changes: 33 additions & 10 deletions src/prisma/prisma.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { HttpException, HttpStatus, Injectable } from "@nestjs/common";
import {
HttpException,
HttpStatus,
Injectable,
Logger,
OnModuleInit,
} from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { PrismaClient, Role } from "@prisma/client";
import * as argon from "argon2";
Expand All @@ -14,15 +20,32 @@ import {
config();

@Injectable()
export class PrismaService extends PrismaClient {
export class PrismaService extends PrismaClient implements OnModuleInit {
constructor(private readonly config: ConfigService) {
super({
datasources: {
db: {
url: config.get("DATABASE_URL"),
},
},
});
super();
const uriRegExp =
/^mysql:\/\/([a-zA-Z0-9_]+):(.\S+)@([a-zA-Z0-9-.]+)\//;
const url = this.config.get("DATABASE_URL");
if (!url) {
Logger.error("DATABASE_URL not found", "CONFIG");
throw Error("[CONFIG] DATABASE_URL Not Found");
}
Logger.debug("DATABASE_URL Found", "CONFIG");
if (!uriRegExp.exec(url)) {
Logger.error("DATABASE_URL is not valid", "CONFIG");
throw Error("[CONFIG] DATABASE_URL Not Valid");
}
Logger.debug("DATABASE_URL is Valid", "CONFIG");
}

async onModuleInit() {
try {
await this.$connect();
Logger.debug("Connected to Database", "Prisma");
} catch (error) {
Logger.error("Could Not Connect to Database", "PRISMA");
Logger.debug(error, "PRISMA");
}
}

async Slugify(text: string): Promise<string> {
Expand Down Expand Up @@ -50,7 +73,7 @@ export class PrismaService extends PrismaClient {

if (!res) {
throw new HttpException(
`${email} does not exists`,
"Email does not exists",
HttpStatus.FORBIDDEN,
);
}
Expand Down
10 changes: 10 additions & 0 deletions src/supabase/supabase.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Global, Module } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { PrismaService } from "../prisma/prisma.service";

@Global()
@Module({
providers: [ConfigService, PrismaService],
exports: [PrismaService],
})
export class SupabaseModule {}
37 changes: 37 additions & 0 deletions src/supabase/supabase.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Injectable } from "@nestjs/common";
import { Express } from "express";
import * as fs from "fs";

Check failure on line 3 in src/supabase/supabase.service.ts

View workflow job for this annotation

GitHub Actions / lint-and-build

'fs' is defined but never used
import { Multer } from "multer";

Check failure on line 4 in src/supabase/supabase.service.ts

View workflow job for this annotation

GitHub Actions / lint-and-build

'Multer' is defined but never used
import { createClient } from "@supabase/supabase-js";
import { timestamp } from "rxjs";

Check failure on line 6 in src/supabase/supabase.service.ts

View workflow job for this annotation

GitHub Actions / lint-and-build

'timestamp' is defined but never used
import * as timers from "timers";

Check failure on line 7 in src/supabase/supabase.service.ts

View workflow job for this annotation

GitHub Actions / lint-and-build

'timers' is defined but never used

const supabase = createClient(
// TODO: implement config service and constructor
"",
"",
);

@Injectable()
export class SupabaseService {
async uploadFile(file: Express.Multer.File) {
const time = Date.now();
const { data, error } = await supabase.storage
.from("EzMs-bucket")
.upload(
`/data/${file.originalname}-${time}.${
file.mimetype.split("/")[1]
}`,
file.buffer,
);

console.log(data);

if (error) {
// Handle error
throw error;
} else {
return data.path;
}
}
}

0 comments on commit fd1bfce

Please sign in to comment.