diff --git a/dictation_server/src/common/validators/IsUnique.validator.ts b/dictation_server/src/common/validators/IsUnique.validator.ts index 21ad6f0..2b6547c 100644 --- a/dictation_server/src/common/validators/IsUnique.validator.ts +++ b/dictation_server/src/common/validators/IsUnique.validator.ts @@ -8,8 +8,7 @@ import { @ValidatorConstraint() export class IsUniqueArray implements ValidatorConstraintInterface { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - validate(arr: any[], args: ValidationArguments) { + validate(arr: any[]) { return arr.length === new Set(arr).size; } diff --git a/dictation_server/src/common/validators/admin.validator.ts b/dictation_server/src/common/validators/admin.validator.ts index 7a023cd..53ac507 100644 --- a/dictation_server/src/common/validators/admin.validator.ts +++ b/dictation_server/src/common/validators/admin.validator.ts @@ -1,6 +1,30 @@ -import { registerDecorator, ValidationOptions } from 'class-validator'; +import { + registerDecorator, + ValidationOptions, + ValidatorConstraint, + ValidatorConstraintInterface, +} from 'class-validator'; + +@ValidatorConstraint() +export class IsAdminPassword implements ValidatorConstraintInterface { + validate(value: string): boolean { + // 8文字~64文字でなければ早期に不合格 + const minLength = 8; + const maxLength = 64; + if (value.length < minLength || value.length > maxLength) { + return false; + } + + // 英字の大文字、英字の小文字、アラビア数字、記号(@#$%^&*\-_+=[]{}|\:',.?/`~"();!)から2種類以上組み合わせ + const charaTypePattern = + /^((?=.*[a-z])(?=.*[A-Z])|(?=.*[a-z])(?=.*[\d])|(?=.*[a-z])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!])|(?=.*[A-Z])(?=.*[\d])|(?=.*[A-Z])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!])|(?=.*[\d])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!]))[a-zA-Z\d@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!]/; + return new RegExp(charaTypePattern).test(value); + } + defaultMessage(): string { + return 'Admin password rule not satisfied'; + } +} -// TODO タスク 2502: バリデータをクラスを使用した記述に統一するで修正する export const IsAdminPasswordvalid = (validationOptions?: ValidationOptions) => { return (object: any, propertyName: string) => { registerDecorator({ @@ -9,24 +33,7 @@ export const IsAdminPasswordvalid = (validationOptions?: ValidationOptions) => { propertyName: propertyName, constraints: [], options: validationOptions, - validator: { - validate: (value: string) => { - // 8文字~64文字でなければ早期に不合格 - const minLength = 8; - const maxLength = 64; - if (value.length < minLength || value.length > maxLength) { - return false; - } - - // 英字の大文字、英字の小文字、アラビア数字、記号(@#$%^&*\-_+=[]{}|\:',.?/`~"();!)から2種類以上組み合わせ - const charaTypePattern = - /^((?=.*[a-z])(?=.*[A-Z])|(?=.*[a-z])(?=.*[\d])|(?=.*[a-z])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!])|(?=.*[A-Z])(?=.*[\d])|(?=.*[A-Z])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!])|(?=.*[\d])(?=.*[@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!]))[a-zA-Z\d@#$%^&*\\\-_+=\[\]{}|:',.?\/`~"();!]/; - return new RegExp(charaTypePattern).test(value); - }, - defaultMessage: () => { - return 'Admin password rule not satisfied'; - }, - }, + validator: IsAdminPassword, }); }; }; diff --git a/dictation_server/src/common/validators/assignees.validator.ts b/dictation_server/src/common/validators/assignees.validator.ts index 5f9b100..45550d0 100644 --- a/dictation_server/src/common/validators/assignees.validator.ts +++ b/dictation_server/src/common/validators/assignees.validator.ts @@ -1,10 +1,33 @@ import { registerDecorator, ValidationOptions, - ValidationArguments, + ValidatorConstraint, + ValidatorConstraintInterface, } from 'class-validator'; import { Assignee } from '../../features/tasks/types/types'; -// TODO タスク 2502: バリデータをクラスを使用した記述に統一するで修正する + +@ValidatorConstraint() +export class IsTypist implements ValidatorConstraintInterface { + validate(values: Assignee[]): boolean { + return values.every((value) => { + const { typistUserId, typistGroupId, typistName } = value; + if (typistUserId === undefined && typistGroupId === undefined) { + return false; + } + if (typistUserId !== undefined && typistGroupId !== undefined) { + return false; + } + if (!typistName) { + return false; + } + return true; + }); + } + defaultMessage(): string { + return 'Request body is invalid format'; + } +} + /** * Validations options * @param [validationOptions] @@ -17,28 +40,7 @@ export const IsAssignees = (validationOptions?: ValidationOptions) => { target: object.constructor, propertyName: propertyName, options: validationOptions, - validator: { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - validate: (values: Assignee[], args: ValidationArguments) => { - return values.every((value) => { - const { typistUserId, typistGroupId, typistName } = value; - if (typistUserId === undefined && typistGroupId === undefined) { - return false; - } - if (typistUserId !== undefined && typistGroupId !== undefined) { - return false; - } - if (!typistName) { - return false; - } - return true; - }); - }, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - defaultMessage: (args?: ValidationArguments): string => { - return 'Request body is invalid format'; - }, - }, + validator: IsTypist, }); }; }; diff --git a/dictation_server/src/common/validators/encryptionPassword.validator.ts b/dictation_server/src/common/validators/encryptionPassword.validator.ts index 8492628..bed02f9 100644 --- a/dictation_server/src/common/validators/encryptionPassword.validator.ts +++ b/dictation_server/src/common/validators/encryptionPassword.validator.ts @@ -2,9 +2,46 @@ import { registerDecorator, ValidationArguments, ValidationOptions, + ValidatorConstraint, + ValidatorConstraintInterface, } from 'class-validator'; import { SignupRequest } from '../../features/users/types/types'; -// TODO タスク 2502: バリデータをクラスを使用した記述に統一するで修正する + +@ValidatorConstraint() +export class IsPassword implements ValidatorConstraintInterface { + validate(value: string | undefined): boolean { + // passwordが設定されていない場合はチェックしない + if (value === undefined) { + return true; + } + // 正規表現でパスワードのチェックを行う + // 4~16文字の半角英数字と記号のみ + const regex = /^[!-~]{4,16}$/; + if (!regex.test(value)) { + return false; + } + + return true; + } + defaultMessage(): string { + return 'EncryptionPassword rule not satisfied'; + } +} + +@ValidatorConstraint() +export class IsEncryptionPassword implements ValidatorConstraintInterface { + validate(value: string | undefined, args: ValidationArguments): boolean { + const { encryption } = args.object as SignupRequest; + if (encryption === true && !value) { + return false; + } + return true; + } + defaultMessage(): string { + return 'Encryption password is required when encryption is enabled'; + } +} + export const IsPasswordvalid = (validationOptions?: ValidationOptions) => { return (object: any, propertyName: string) => { registerDecorator({ @@ -13,29 +50,10 @@ export const IsPasswordvalid = (validationOptions?: ValidationOptions) => { propertyName: propertyName, constraints: [], options: validationOptions, - validator: { - validate: (value: string | undefined) => { - // passwordが設定されていない場合はチェックしない - if (value === undefined) { - return true; - } - // 正規表現でパスワードのチェックを行う - // 4~16文字の半角英数字と記号のみ - const regex = /^[!-~]{4,16}$/; - if (!regex.test(value)) { - return false; - } - - return true; - }, - defaultMessage: () => { - return 'EncryptionPassword rule not satisfied'; - }, - }, + validator: IsPassword, }); }; }; -// TODO タスク 2502: バリデータをクラスを使用した記述に統一するで修正する export const IsEncryptionPasswordPresent = ( validationOptions?: ValidationOptions, ) => { @@ -46,18 +64,7 @@ export const IsEncryptionPasswordPresent = ( propertyName: propertyName, constraints: [], options: validationOptions, - validator: { - validate: (value: string | undefined, args: ValidationArguments) => { - const { encryption } = args.object as SignupRequest; - if (encryption === true && !value) { - return false; - } - return true; - }, - defaultMessage: () => { - return 'Encryption password is required when encryption is enabled'; - }, - }, + validator: IsEncryptionPassword, }); }; }; diff --git a/dictation_server/src/common/validators/roleAuthor.validator.ts b/dictation_server/src/common/validators/roleAuthor.validator.ts index 67efa15..c0fe0d0 100644 --- a/dictation_server/src/common/validators/roleAuthor.validator.ts +++ b/dictation_server/src/common/validators/roleAuthor.validator.ts @@ -2,6 +2,8 @@ import { registerDecorator, ValidationArguments, ValidationOptions, + ValidatorConstraint, + ValidatorConstraintInterface, } from 'class-validator'; import { PostUpdateUserRequest, @@ -9,7 +11,26 @@ import { } from '../../features/users/types/types'; import { USER_ROLES } from '../../constants'; -// TODO タスク 2502: バリデータをクラスを使用した記述に統一するで修正する +@ValidatorConstraint() +export class IsRoleAuthorData implements ValidatorConstraintInterface { + propertyName: string; + constructor(propertyName: string) { + this.propertyName = propertyName; + } + + validate(value: any, args: ValidationArguments): boolean { + const request = args.object as SignupRequest | PostUpdateUserRequest; + const { role } = request; + if (role === USER_ROLES.AUTHOR && value === undefined) { + return false; + } + return true; + } + defaultMessage(): string { + return `When role is author, ${this.propertyName} cannot be undefined`; + } +} + export const IsRoleAuthorDataValid = < T extends SignupRequest | PostUpdateUserRequest, >( @@ -22,19 +43,7 @@ export const IsRoleAuthorDataValid = < propertyName: propertyName, constraints: [], options: validationOptions, - validator: { - validate: (value: any, args: ValidationArguments) => { - const request = args.object as T; - const { role } = request; - if (role === USER_ROLES.AUTHOR && value === undefined) { - return false; - } - return true; - }, - defaultMessage: () => { - return `When role is author, ${propertyName} cannot be undefined`; - }, - }, + validator: new IsRoleAuthorData(propertyName), }); }; }; diff --git a/dictation_server/src/common/validators/status.validator.ts b/dictation_server/src/common/validators/status.validator.ts index eca361e..412d2a4 100644 --- a/dictation_server/src/common/validators/status.validator.ts +++ b/dictation_server/src/common/validators/status.validator.ts @@ -10,8 +10,7 @@ import { TASK_STATUS } from '../../constants'; @ValidatorConstraint() export class IsStatusConstraint implements ValidatorConstraintInterface { private readonly STATUS: string[] = Object.values(TASK_STATUS); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - validate(value: string, args: ValidationArguments): boolean { + validate(value: string): boolean { if (value) { // ,で分割した文字列のすべてがTASK_STATUSのプロパティに存在する値であった場合のみtrue return value.split(',').every((state) => this.STATUS.includes(state)); @@ -20,8 +19,7 @@ export class IsStatusConstraint implements ValidatorConstraintInterface { } } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - defaultMessage(validationArguments?: ValidationArguments): string { + defaultMessage(): string { return `invalid status string`; } }