diff --git a/package.json b/package.json index 33dba06..6bb98f0 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,8 @@ "@nestjs/graphql": "^12.2.1", "@nestjs/platform-express": "^10.0.0", "@prisma/client": "^6.0.0", + "class-transformer": "^0.5.1", + "class-validator": "^0.14.1", "dotenv": "^16.4.5", "dotenv-cli": "^7.4.2", "env-var": "^7.5.0", diff --git a/src/main.ts b/src/main.ts index 0d641ea..d998397 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,5 +1,6 @@ import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; +import { ValidationPipe } from '@nestjs/common'; async function bootstrap() { const app = await NestFactory.create(AppModule); @@ -10,6 +11,8 @@ async function bootstrap() { methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'], }); + app.useGlobalPipes(new ValidationPipe({ whitelist: true, transform: true })); + await app.listen(process.env.PORT ?? 3000); } bootstrap(); diff --git a/src/resolvers/campaign.resolver.ts b/src/resolvers/campaign.resolver.ts index b5243ff..8362d56 100644 --- a/src/resolvers/campaign.resolver.ts +++ b/src/resolvers/campaign.resolver.ts @@ -1,5 +1,11 @@ -import { BadRequestException, Logger, NotFoundException } from '@nestjs/common'; -import { Args, Int, Mutation, Query, Resolver } from '@nestjs/graphql'; +import { + NotFoundException, + BadRequestException, + Logger, + UsePipes, + ValidationPipe, +} from '@nestjs/common'; +import { Resolver, Query, Args, Mutation, Int } from '@nestjs/graphql'; import { PrismaService } from 'src/prisma/prisma.service'; import { Campaign } from './models/campaign.model'; import { CampaignCreateInput } from './dtos/createCampaign.dto'; @@ -13,6 +19,7 @@ export class CampaignResolver { constructor(private prismaService: PrismaService) {} @Mutation(() => Campaign) + @UsePipes(new ValidationPipe({ whitelist: true, transform: true })) async createCampaign( @Args('campaignData') campaignData: CampaignCreateInput, ): Promise { @@ -32,11 +39,7 @@ export class CampaignResolver { @Query(() => CampaignConnection) async getAllCampaigns( @Args('cursor', { nullable: true }) cursor?: string, - @Args('limit', { - type: () => Int, - nullable: true, - defaultValue: 10, - }) + @Args('limit', { type: () => Int, nullable: true, defaultValue: 10 }) limit?: number, ): Promise { try { diff --git a/src/resolvers/dtos/createCampaign.dto.ts b/src/resolvers/dtos/createCampaign.dto.ts index 8f4923c..6964976 100644 --- a/src/resolvers/dtos/createCampaign.dto.ts +++ b/src/resolvers/dtos/createCampaign.dto.ts @@ -1,36 +1,52 @@ import { InputType, Field, Int } from '@nestjs/graphql'; +import { IsString, IsNotEmpty, IsInt, IsOptional } from 'class-validator'; import GraphQLJSON from 'graphql-type-json'; import { InputJsonObject } from '@prisma/client/runtime/library'; @InputType() export class CampaignCreateInput { @Field(() => Int) + @IsInt() campaign_id: number; @Field(() => String) + @IsNotEmpty() + @IsString() campaign_name: string; @Field(() => String) + @IsNotEmpty() + @IsString() campaign_description: string; @Field(() => String) + @IsNotEmpty() + @IsString() cover_photo: string; - @Field(() => GraphQLJSON, { nullable: true }) - social_links?: InputJsonObject; - @Field(() => Int) + @IsInt() target_amount: number; @Field(() => Int, { nullable: true }) + @IsOptional() + @IsInt() totalDonations?: number; @Field(() => String) + @IsNotEmpty() + @IsString() organizer: string; @Field(() => String) + @IsNotEmpty() + @IsString() beneficiary: string; @Field(() => Int, { nullable: true }) + @IsOptional() + @IsInt() category_id?: number; + @Field(() => GraphQLJSON, { nullable: true }) + social_links?: InputJsonObject; } diff --git a/yarn.lock b/yarn.lock index f6bbedf..b691342 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1497,6 +1497,11 @@ "@types/methods" "^1.1.4" "@types/superagent" "^8.1.0" +"@types/validator@^13.11.8": + version "13.12.2" + resolved "https://registry.yarnpkg.com/@types/validator/-/validator-13.12.2.tgz#760329e756e18a4aab82fc502b51ebdfebbe49f5" + integrity sha512-6SlHBzUW8Jhf3liqrGGXyTJSIFe4nqlJ5A5KaMZ2l/vbM3Wh3KSybots/wfWVzNLK4D1NZluDlSQIbIEPx6oyA== + "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -2211,6 +2216,20 @@ cjs-module-lexer@^1.0.0: resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz#0f79731eb8cfe1ec72acd4066efac9d61991b00d" integrity sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q== +class-transformer@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/class-transformer/-/class-transformer-0.5.1.tgz#24147d5dffd2a6cea930a3250a677addf96ab336" + integrity sha512-SQa1Ws6hUbfC98vKGxZH3KFY0Y1lm5Zm0SY8XX9zbK7FJCyVEac3ATW0RIpwzW+oOfmHE5PMPufDG9hCfoEOMw== + +class-validator@^0.14.1: + version "0.14.1" + resolved "https://registry.yarnpkg.com/class-validator/-/class-validator-0.14.1.tgz#ff2411ed8134e9d76acfeb14872884448be98110" + integrity sha512-2VEG9JICxIqTpoK1eMzZqaV+u/EiwEJkMGzTrZf6sU/fwsnOITVgYJ8yojSy6CaXtO9V0Cc6ZQZ8h8m4UBuLwQ== + dependencies: + "@types/validator" "^13.11.8" + libphonenumber-js "^1.10.53" + validator "^13.9.0" + cli-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" @@ -4065,6 +4084,11 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +libphonenumber-js@^1.10.53: + version "1.12.4" + resolved "https://registry.yarnpkg.com/libphonenumber-js/-/libphonenumber-js-1.12.4.tgz#15062e61ac29d381305f0a37b0c2aad6ae432931" + integrity sha512-vLmhg7Gan7idyAKfc6pvCtNzvar4/eIzrVVk3hjNFH5+fGqyjD0gQRovdTrDl20wsmZhBtmZpcsR0tOfquwb8g== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -5605,6 +5629,11 @@ v8-to-istanbul@^9.0.1: "@types/istanbul-lib-coverage" "^2.0.1" convert-source-map "^2.0.0" +validator@^13.9.0: + version "13.12.0" + resolved "https://registry.yarnpkg.com/validator/-/validator-13.12.0.tgz#7d78e76ba85504da3fee4fd1922b385914d4b35f" + integrity sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg== + value-or-promise@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/value-or-promise/-/value-or-promise-1.0.12.tgz#0e5abfeec70148c78460a849f6b003ea7986f15c"