Validation.ts 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import { MetricType, METRIC_TYPES_VALUES } from '../consts/Milvus';
  2. export type ValidType =
  3. | 'email'
  4. | 'require'
  5. | 'confirm'
  6. | 'range'
  7. | 'password'
  8. | 'clusterName'
  9. | 'CIDRorIP'
  10. | 'integer'
  11. | 'positiveNumber'
  12. | 'collectionName'
  13. | 'dimension'
  14. | 'multiple'
  15. | 'partitionName'
  16. | 'firstCharacter'
  17. | 'specValueOrRange';
  18. export interface ICheckMapParam {
  19. value: string;
  20. extraParam?: IExtraParam;
  21. rule: ValidType;
  22. }
  23. export interface IExtraParam {
  24. // used for confirm or any compare type
  25. compareValue?: string | number;
  26. // used for length type
  27. min?: number;
  28. max?: number;
  29. type?: 'string' | 'number';
  30. // used for dimension
  31. metricType?: MetricType;
  32. multipleNumber?: number;
  33. // used for check start item
  34. invalidTypes?: TypeEnum[];
  35. }
  36. export type CheckMap = {
  37. [key in ValidType]: boolean;
  38. };
  39. export enum TypeEnum {
  40. 'number' = 'number',
  41. }
  42. export const checkEmptyValid = (value: string): boolean => {
  43. return value.trim() !== '';
  44. };
  45. export const checkEmail = (value: string): boolean => {
  46. const re = /\S+@\S+\.\S+/;
  47. return re.test(value);
  48. };
  49. /* password rules:
  50. * 1. at least one uppercase letter
  51. * 2. at least one lowercase letter
  52. * 3. at least one number
  53. * 4. at least one nonalphanumeric character: ! @ # $ % ^ & * ( ) _ + - = [ ] { } | '
  54. */
  55. export const checkPasswordStrength = (value: string): boolean => {
  56. const re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*([^A-Za-z0-9]))/;
  57. return re.test(value);
  58. };
  59. export const checkRange = (param: {
  60. value: string | number;
  61. min?: number;
  62. max?: number;
  63. type?: 'string' | 'number';
  64. }): boolean => {
  65. const { value, min = 0, max = 0, type } = param;
  66. const length = type === 'number' ? Number(value) : (value as string).length;
  67. let result = true;
  68. const conditionMap = {
  69. min: length >= min,
  70. max: length <= max,
  71. };
  72. if (min !== 0) {
  73. result = result && conditionMap.min;
  74. }
  75. if (max !== 0) {
  76. result = result && conditionMap.max;
  77. }
  78. return result;
  79. };
  80. export const checkClusterName = (value: string): boolean => {
  81. const re = new RegExp('^[A-Za-z0-9+-=._:@/ ]*$');
  82. return re.test(value);
  83. };
  84. export const checkIP = (value: string): boolean => {
  85. const re =
  86. /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
  87. return re.test(value);
  88. };
  89. export const checkCIDR = (value: string): boolean => {
  90. const re =
  91. /^(?:(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\/([0-9]|[1-2]\d|3[0-2])$/;
  92. return re.test(value);
  93. };
  94. export const checkIpOrCIDR = (value: string): boolean => {
  95. // const re = new RegExp('^([0-9]{1,3}.){3}[0-9]{1,3}($|/(16|24)$)');
  96. // return re.test(value);
  97. return checkIP(value) || checkCIDR(value);
  98. };
  99. // collection name can only be combined with number, letter or _
  100. export const checkCollectionName = (value: string): boolean => {
  101. const re = /^[0-9,a-z,A-Z_]+$/;
  102. return re.test(value);
  103. };
  104. /**
  105. * check data type
  106. * @param type data types, like string, number
  107. * @param value
  108. * @returns whether value's value is equal to param type
  109. */
  110. export const checkType = (type: TypeEnum, value: string): boolean => {
  111. switch (type) {
  112. case TypeEnum.number:
  113. return !isNaN(Number(value));
  114. default:
  115. return true;
  116. }
  117. };
  118. /**
  119. * check input first character
  120. * @param value
  121. * @param invalidTypes
  122. * @returns whether start letter type not belongs to invalid types
  123. */
  124. export const checkFirstCharacter = (param: {
  125. value: string;
  126. invalidTypes?: TypeEnum[];
  127. }): boolean => {
  128. const { value, invalidTypes } = param;
  129. const start = value[0];
  130. const types = invalidTypes || [];
  131. for (let type of types) {
  132. const result = checkType(type, start);
  133. if (result) {
  134. return false;
  135. }
  136. }
  137. return true;
  138. };
  139. export const checkPartitionName = (value: string): boolean => {
  140. return value !== '_default';
  141. };
  142. export const checkMultiple = (param: {
  143. value: string;
  144. multipleNumber?: number;
  145. }): boolean => {
  146. const { value, multipleNumber = 1 } = param;
  147. return Number(value) % multipleNumber === 0;
  148. };
  149. export const checkDimension = (param: {
  150. value: string;
  151. metricType?: MetricType;
  152. multipleNumber?: number;
  153. }): boolean => {
  154. const { value, metricType, multipleNumber } = param;
  155. if (
  156. metricType === METRIC_TYPES_VALUES.IP ||
  157. metricType === METRIC_TYPES_VALUES.L2
  158. ) {
  159. return true;
  160. }
  161. return checkMultiple({ value, multipleNumber });
  162. };
  163. /**
  164. * function to check whether value(type: number) is equal to specified value or in valid range
  165. * @param param specValue and params checkRange function needed
  166. * @returns whether input is valid
  167. */
  168. export const checkSpecValueOrRange = (param: {
  169. value: number;
  170. min: number;
  171. max: number;
  172. compareValue: number;
  173. }): boolean => {
  174. const { value, min, max, compareValue } = param;
  175. return (
  176. value === compareValue || checkRange({ min, max, value, type: 'number' })
  177. );
  178. };
  179. export const getCheckResult = (param: ICheckMapParam): boolean => {
  180. const { value, extraParam = {}, rule } = param;
  181. const numberValue = Number(value);
  182. const checkMap = {
  183. email: checkEmail(value),
  184. require: checkEmptyValid(value),
  185. confirm: value === extraParam?.compareValue,
  186. range: checkRange({
  187. value,
  188. min: extraParam?.min,
  189. max: extraParam?.max,
  190. type: extraParam?.type,
  191. }),
  192. password: checkPasswordStrength(value),
  193. clusterName: checkClusterName(value),
  194. CIDRorIP: checkIpOrCIDR(value),
  195. integer: !isNaN(numberValue) && Number.isInteger(numberValue),
  196. positiveNumber: !isNaN(numberValue) && numberValue > 0,
  197. collectionName: checkCollectionName(value),
  198. dimension: checkDimension({
  199. value,
  200. metricType: extraParam?.metricType,
  201. multipleNumber: extraParam?.multipleNumber,
  202. }),
  203. multiple: checkMultiple({
  204. value,
  205. multipleNumber: extraParam?.multipleNumber,
  206. }),
  207. partitionName: checkPartitionName(value),
  208. firstCharacter: checkFirstCharacter({
  209. value,
  210. invalidTypes: extraParam?.invalidTypes,
  211. }),
  212. specValueOrRange: checkSpecValueOrRange({
  213. value: Number(value),
  214. min: extraParam?.min || 0,
  215. max: extraParam?.max || 0,
  216. compareValue: Number(extraParam.compareValue) || 0,
  217. }),
  218. };
  219. return checkMap[rule];
  220. };