From 2009d1c28c4367514223c6ba1193ada405e3aab9 Mon Sep 17 00:00:00 2001 From: Kshitija Kadam <65657373+Xitija@users.noreply.github.com> Date: Fri, 2 Aug 2024 18:14:42 +0530 Subject: [PATCH] Task #224395 : feat - Validate meeting links as per provider --- src/common/utils/validation.util.ts | 41 +++++++++++++++++++++++ src/modules/event/dto/create-event.dto.ts | 15 ++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 src/common/utils/validation.util.ts diff --git a/src/common/utils/validation.util.ts b/src/common/utils/validation.util.ts new file mode 100644 index 0000000..9beb877 --- /dev/null +++ b/src/common/utils/validation.util.ts @@ -0,0 +1,41 @@ +import { + ValidatorConstraint, + ValidatorConstraintInterface, + ValidationArguments, +} from 'class-validator'; + +function validateMeetingUrl(url, provider) { + const providerPatterns = { + zoom: /^https:\/\/[\w-]*\.?zoom.us\/(j|my)\/[\d\w?=-]+$/, + googlemeet: /^(https:\/\/)?meet\.google\.com\/[a-zA-Z0-9-]+$/, + // microsoftteams: /^(https:\/\/)?teams\.microsoft\.com\/[a-zA-Z0-9?&=]+$/, + // Add other supported providers as needed + }; + if ( + !url || + typeof url !== 'string' || + !provider || + typeof provider !== 'string' + ) { + return false; + } + + const pattern = providerPatterns[provider.toLowerCase()]; + if (!pattern) { + return false; // Unsupported provider + } + + return pattern.test(url); +} + +@ValidatorConstraint({ name: 'urlWithProviderValidator', async: false }) +export class UrlWithProviderValidator implements ValidatorConstraintInterface { + validate(url: string, args: ValidationArguments) { + const { onlineProvider } = args.object as any; + return validateMeetingUrl(url, onlineProvider); + } + + defaultMessage(args: ValidationArguments) { + return 'Invalid meeting URL for the specified provider!'; + } +} diff --git a/src/modules/event/dto/create-event.dto.ts b/src/modules/event/dto/create-event.dto.ts index f14a4ea..ebd25dc 100644 --- a/src/modules/event/dto/create-event.dto.ts +++ b/src/modules/event/dto/create-event.dto.ts @@ -21,7 +21,7 @@ import { IsIn, } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; -import { Type } from 'class-transformer'; +import { Transform, Type } from 'class-transformer'; import { EndConditionType, EventTypes, @@ -31,8 +31,12 @@ import { } from 'src/common/utils/types'; import { ERROR_MESSAGES } from 'src/common/utils/constants.util'; import { EndsWithZConstraint } from 'src/common/pipes/event-validation.pipe'; +import { UrlWithProviderValidator } from 'src/common/utils/validation.util'; export class MeetingDetailsDto { + // Pass the provider from the parent DTO + onlineProvider: string; + @ApiProperty({ description: 'Meeting ID', example: 94292617 }) @IsString() @IsNotEmpty() @@ -44,7 +48,7 @@ export class MeetingDetailsDto { }) @IsString() @IsNotEmpty() - // @Validate(UrlValidator) + @Validate(UrlWithProviderValidator) url: string; @ApiProperty({ description: 'Meeting password', example: 'xxxxxx' }) @@ -253,7 +257,7 @@ export class CreateEventDto { @ValidateIf((o) => o.eventType === EventTypes.online) @IsString() @IsNotEmpty() - @IsIn(['Zoom', 'GoogleMeet', 'MicrosoftTeams']) // Supported providers + @IsIn(['Zoom', 'GoogleMeet']) //, 'MicrosoftTeams' // Supported providers onlineProvider: string; @ApiProperty({ @@ -279,8 +283,11 @@ export class CreateEventDto { @ValidateIf((o) => o.eventType === 'online') @ValidateNested({ each: true }) @Type(() => MeetingDetailsDto) + @Transform(({ value, obj }) => { + value.onlineProvider = obj.onlineProvider; // Pass the provider to the nested DTO + return value; + }) meetingDetails: MeetingDetails; - // TODO: meet url validation @ApiProperty({ type: Number,