Validation.ts 7.5 KB

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