diff --git a/backend/src/graphql/arg/SearchContributionsFilterArgs.ts b/backend/src/graphql/arg/SearchContributionsFilterArgs.ts index e256fa663..29446f1df 100644 --- a/backend/src/graphql/arg/SearchContributionsFilterArgs.ts +++ b/backend/src/graphql/arg/SearchContributionsFilterArgs.ts @@ -1,18 +1,24 @@ +import { IsBoolean, IsPositive, IsString } from 'class-validator' import { Field, ArgsType, Int } from 'type-graphql' import { ContributionStatus } from '@enum/ContributionStatus' +import { isContributionStatusArray } from '@/graphql/validator/ContributionStatusArray' @ArgsType() export class SearchContributionsFilterArgs { @Field(() => [ContributionStatus], { nullable: true, defaultValue: null }) + @isContributionStatusArray() statusFilter?: ContributionStatus[] | null @Field(() => Int, { nullable: true }) + @IsPositive() userId?: number | null @Field(() => String, { nullable: true, defaultValue: '' }) + @IsString() query?: string | null @Field(() => Boolean, { nullable: true }) + @IsBoolean() noHashtag?: boolean | null } diff --git a/backend/src/graphql/resolver/ContributionResolver.test.ts b/backend/src/graphql/resolver/ContributionResolver.test.ts index 167edfe74..52dd04339 100644 --- a/backend/src/graphql/resolver/ContributionResolver.test.ts +++ b/backend/src/graphql/resolver/ContributionResolver.test.ts @@ -2792,11 +2792,28 @@ describe('ContributionResolver', () => { resetToken() }) + it('throw error for invalid ContributionStatus in statusFilter array', async() => { + const { errors: errorObjects } = await query({ + query: adminListContributions, + variables: { + statusFilter:["INVALID_STATUS"] + } + }) + expect(errorObjects).toMatchObject([ + { + message: "Variable \"$statusFilter\" got invalid value \"INVALID_STATUS\" at \"statusFilter[0]\"; Value \"INVALID_STATUS\" does not exist in \"ContributionStatus\" enum.", + extensions: { + code: "BAD_USER_INPUT" + }, + }, + ]) + }) + it('returns 17 creations in total', async () => { const { data: { adminListContributions: contributionListObject }, } = await query({ - query: adminListContributions, + query: adminListContributions }) expect(contributionListObject.contributionList).toHaveLength(17) expect(contributionListObject).toMatchObject({ diff --git a/backend/src/graphql/schema.ts b/backend/src/graphql/schema.ts index 18214861f..caca1b5bc 100644 --- a/backend/src/graphql/schema.ts +++ b/backend/src/graphql/schema.ts @@ -12,8 +12,9 @@ export const schema = async (): Promise => { resolvers: [path.join(__dirname, 'resolver', `!(*.test).{js,ts}`)], authChecker: isAuthorized, scalarsMap: [{ type: Decimal, scalar: DecimalScalar }], + emitSchemaFile: true, validate: { - validationError: { target: false }, + validationError: { target: true }, skipMissingProperties: true, skipNullProperties: true, skipUndefinedProperties: false, diff --git a/backend/src/graphql/validator/ContributionStatusArray.ts b/backend/src/graphql/validator/ContributionStatusArray.ts new file mode 100644 index 000000000..da718f70c --- /dev/null +++ b/backend/src/graphql/validator/ContributionStatusArray.ts @@ -0,0 +1,21 @@ +import { registerDecorator, ValidationOptions } from 'class-validator' + +import { ContributionStatus } from '@enum/ContributionStatus' + +export function isContributionStatusArray(validationOptions?: ValidationOptions) { + // eslint-disable-next-line @typescript-eslint/ban-types + return function (object: Object, propertyName: string) { + registerDecorator({ + name: 'isContributionStatusArray', + target: object.constructor, + propertyName, + options: validationOptions, + validator: { + validate(value: ContributionStatus[]): boolean { + const validValues = Object.values(ContributionStatus) + return value.every((item) => validValues.includes(item)) + }, + }, + }) + } +} diff --git a/backend/src/seeds/graphql/queries.ts b/backend/src/seeds/graphql/queries.ts index 3dda2633c..949ed86d7 100644 --- a/backend/src/seeds/graphql/queries.ts +++ b/backend/src/seeds/graphql/queries.ts @@ -251,6 +251,7 @@ export const adminListContributions = gql` $statusFilter: [ContributionStatus!] $userId: Int $query: String + $noHashtag: Boolean ) { adminListContributions( currentPage: $currentPage @@ -259,6 +260,7 @@ export const adminListContributions = gql` statusFilter: $statusFilter userId: $userId query: $query + noHashtag: $noHashtag ) { contributionCount contributionList {