@cloud-ru/uikit-product-claudia 1.11.0 → 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/cjs/components/SshField/SshField.js +33 -46
  3. package/dist/cjs/components/SshField/components/MobileFieldAi/MobileFieldAi.d.ts +3 -0
  4. package/dist/cjs/components/SshField/components/MobileFieldAi/MobileFieldAi.js +2 -2
  5. package/dist/cjs/components/SshField/helperComponents/CheckItem/CheckItem.d.ts +6 -0
  6. package/dist/cjs/components/SshField/helperComponents/CheckItem/CheckItem.js +13 -0
  7. package/dist/cjs/components/SshField/helperComponents/CheckItem/index.d.ts +1 -0
  8. package/dist/cjs/components/SshField/helperComponents/CheckItem/index.js +17 -0
  9. package/dist/cjs/components/SshField/helperComponents/CheckItem/styles.module.css +25 -0
  10. package/dist/cjs/components/SshField/helperComponents/DropZoneContent/styles.module.css +1 -1
  11. package/dist/cjs/components/SshField/helperComponents/SshValidation/SshValidation.d.ts +6 -0
  12. package/dist/cjs/components/SshField/helperComponents/SshValidation/SshValidation.js +16 -0
  13. package/dist/cjs/components/SshField/helperComponents/SshValidation/index.d.ts +1 -0
  14. package/dist/cjs/components/SshField/helperComponents/SshValidation/index.js +17 -0
  15. package/dist/cjs/components/SshField/helperComponents/SshValidation/styles.module.css +35 -0
  16. package/dist/cjs/components/SshField/helperComponents/WithSshValidation/WithSshValidation.d.ts +8 -0
  17. package/dist/cjs/components/SshField/helperComponents/WithSshValidation/WithSshValidation.js +19 -0
  18. package/dist/cjs/components/SshField/helperComponents/WithSshValidation/index.d.ts +1 -0
  19. package/dist/cjs/components/SshField/helperComponents/WithSshValidation/index.js +17 -0
  20. package/dist/cjs/components/SshField/helperComponents/WithSshValidation/styles.module.css +5 -0
  21. package/dist/cjs/components/SshField/types.d.ts +12 -0
  22. package/dist/cjs/components/SshField/types.js +2 -0
  23. package/dist/cjs/components/SshField/utils/readFileContent.d.ts +6 -1
  24. package/dist/cjs/components/SshField/utils/readFileContent.js +6 -11
  25. package/dist/cjs/components/SshField/utils/validateSSHKey.d.ts +9 -3
  26. package/dist/cjs/components/SshField/utils/validateSSHKey.js +56 -59
  27. package/dist/esm/components/SshField/SshField.js +34 -47
  28. package/dist/esm/components/SshField/components/MobileFieldAi/MobileFieldAi.d.ts +3 -0
  29. package/dist/esm/components/SshField/components/MobileFieldAi/MobileFieldAi.js +2 -2
  30. package/dist/esm/components/SshField/helperComponents/CheckItem/CheckItem.d.ts +6 -0
  31. package/dist/esm/components/SshField/helperComponents/CheckItem/CheckItem.js +7 -0
  32. package/dist/esm/components/SshField/helperComponents/CheckItem/index.d.ts +1 -0
  33. package/dist/esm/components/SshField/helperComponents/CheckItem/index.js +1 -0
  34. package/dist/esm/components/SshField/helperComponents/CheckItem/styles.module.css +25 -0
  35. package/dist/esm/components/SshField/helperComponents/DropZoneContent/styles.module.css +1 -1
  36. package/dist/esm/components/SshField/helperComponents/SshValidation/SshValidation.d.ts +6 -0
  37. package/dist/esm/components/SshField/helperComponents/SshValidation/SshValidation.js +10 -0
  38. package/dist/esm/components/SshField/helperComponents/SshValidation/index.d.ts +1 -0
  39. package/dist/esm/components/SshField/helperComponents/SshValidation/index.js +1 -0
  40. package/dist/esm/components/SshField/helperComponents/SshValidation/styles.module.css +35 -0
  41. package/dist/esm/components/SshField/helperComponents/WithSshValidation/WithSshValidation.d.ts +8 -0
  42. package/dist/esm/components/SshField/helperComponents/WithSshValidation/WithSshValidation.js +13 -0
  43. package/dist/esm/components/SshField/helperComponents/WithSshValidation/index.d.ts +1 -0
  44. package/dist/esm/components/SshField/helperComponents/WithSshValidation/index.js +1 -0
  45. package/dist/esm/components/SshField/helperComponents/WithSshValidation/styles.module.css +5 -0
  46. package/dist/esm/components/SshField/types.d.ts +12 -0
  47. package/dist/esm/components/SshField/types.js +1 -0
  48. package/dist/esm/components/SshField/utils/readFileContent.d.ts +6 -1
  49. package/dist/esm/components/SshField/utils/readFileContent.js +6 -11
  50. package/dist/esm/components/SshField/utils/validateSSHKey.d.ts +9 -3
  51. package/dist/esm/components/SshField/utils/validateSSHKey.js +53 -55
  52. package/package.json +6 -5
  53. package/src/components/SshField/SshField.tsx +120 -121
  54. package/src/components/SshField/components/MobileFieldAi/MobileFieldAi.tsx +6 -5
  55. package/src/components/SshField/helperComponents/CheckItem/CheckItem.tsx +23 -0
  56. package/src/components/SshField/helperComponents/CheckItem/index.ts +1 -0
  57. package/src/components/SshField/helperComponents/CheckItem/styles.module.scss +31 -0
  58. package/src/components/SshField/helperComponents/DropZoneContent/styles.module.scss +1 -1
  59. package/src/components/SshField/helperComponents/SshValidation/SshValidation.tsx +36 -0
  60. package/src/components/SshField/helperComponents/SshValidation/index.ts +1 -0
  61. package/src/components/SshField/helperComponents/SshValidation/styles.module.scss +31 -0
  62. package/src/components/SshField/helperComponents/WithSshValidation/WithSshValidation.tsx +43 -0
  63. package/src/components/SshField/helperComponents/WithSshValidation/index.ts +1 -0
  64. package/src/components/SshField/helperComponents/WithSshValidation/styles.module.scss +7 -0
  65. package/src/components/SshField/types.ts +13 -0
  66. package/src/components/SshField/utils/readFileContent.ts +12 -11
  67. package/src/components/SshField/utils/validateSSHKey.ts +60 -68
  68. package/dist/cjs/components/SshField/utils/handleFileError.d.ts +0 -2
  69. package/dist/cjs/components/SshField/utils/handleFileError.js +0 -32
  70. package/dist/esm/components/SshField/utils/handleFileError.d.ts +0 -2
  71. package/dist/esm/components/SshField/utils/handleFileError.js +0 -28
  72. package/src/components/SshField/utils/handleFileError.ts +0 -41
@@ -1,84 +1,76 @@
1
- export const validateSSHKeyContent = (content: string): void => {
2
- const trimmedContent = content.trim();
1
+ const MAX_FILE_SIZE = 10 * 1024; // 10KB по умолчанию
3
2
 
4
- // Проверка на пустой файл
5
- if (trimmedContent.length === 0) {
6
- throw new Error('INVALID_SSH_KEY: Файл пустой');
7
- }
3
+ const SSH_KEY_BEGIN_PATTERN = [
4
+ /^-----BEGIN (?:RSA|DSA|EC|OPENSSH) PRIVATE KEY-----/,
5
+ /^-----BEGIN.*PRIVATE KEY-----/,
6
+ /^-----BEGIN.*CERTIFICATE-----/,
7
+ ];
8
8
 
9
- // Проверка на бинарный файл (простейшая проверка)
10
- const binaryChars = content
11
- .split('')
12
- .filter(char => char.charCodeAt(0) < 32 && char !== '\n' && char !== '\r' && char !== '\t').length;
9
+ const SSH_KEY_END_PATTERN = [
10
+ /-----END (?:RSA|DSA|EC|OPENSSH) PRIVATE KEY-----/,
11
+ /-----END.*PRIVATE KEY-----/,
12
+ /-----END.*CERTIFICATE-----/,
13
+ ];
13
14
 
14
- if (binaryChars > content.length * 0.1) {
15
- // Если больше 10% бинарных символов
16
- throw new Error('INVALID_SSH_KEY: Файл содержит бинарные данные, а не текстовый SSH ключ');
17
- }
15
+ const checkIsFileSizeError = (file: File) => file.size > MAX_FILE_SIZE;
18
16
 
19
- // Базовая проверка на формат SSH ключа
20
- const sshKeyPatterns = [
21
- /^-----BEGIN (?:RSA|DSA|EC|OPENSSH) PRIVATE KEY-----/,
22
- /^ssh-(rsa|dsa|ecdsa|ed25519)/,
23
- /^ecdsa-sha2-nistp/,
24
- /^-----BEGIN.*PRIVATE KEY-----/,
25
- /^-----BEGIN.*CERTIFICATE-----/,
26
- ];
27
-
28
- const isValidSSHKey = sshKeyPatterns.some(pattern => pattern.test(trimmedContent));
29
-
30
- if (!isValidSSHKey) {
31
- throw new Error(
32
- 'INVALID_SSH_KEY: Файл не содержит валидный SSH ключ. Поддерживаются: RSA, DSA, ECDSA, Ed25519 ключи и сертификаты',
33
- );
34
- }
35
- };
17
+ function getFileExtension(filename: string) {
18
+ return filename.includes('.') ? filename.split('.').pop() : '';
19
+ }
36
20
 
37
- const DEFAULT_ALLOWED_MIME_TYPES = ['text/plain'];
38
- const MAX_FILE_SIZE = 10 * 1024; // 10KB по умолчанию
21
+ const checkIsFileTypeError = (file: File) => Boolean(getFileExtension(file.name));
39
22
 
40
- const getFileExtension = (filename: string): string => {
41
- const lastDotIndex = filename.lastIndexOf('.');
23
+ export const validateFileErrors = (file: File) => ({
24
+ fileSize: checkIsFileSizeError(file),
25
+ fileType: checkIsFileTypeError(file),
26
+ });
42
27
 
43
- // Если точка не найдена или это первая точка в имени файла (скрытые файлы в Unix)
44
- if (lastDotIndex <= 0) {
45
- return '';
46
- }
28
+ const checkIsEmptyContent = (value: string) => !value.trim().length;
47
29
 
48
- return filename.toLowerCase().slice(lastDotIndex);
49
- };
30
+ const checkIsBinaryCharsInContent = (value: string) => {
31
+ const binaryChars = value
32
+ .split('')
33
+ .filter(char => char.charCodeAt(0) < 32 && !['\n', '\r', '\t'].includes(char)).length;
50
34
 
51
- const getFileMimeType = (file: File): string => file.type;
35
+ return binaryChars > value.length * 0.1;
36
+ };
52
37
 
53
- export const validateFileType = (file: File): void => {
54
- const fileExtension = getFileExtension(file.name);
55
- const mimeType = getFileMimeType(file);
38
+ const removePEMBoundaries = (sshFileContent: string) => {
39
+ let replacedContent = sshFileContent.trim().replaceAll('\n', '');
40
+ let isBeginPartExist = false;
41
+ let isEndPartExist = false;
42
+
43
+ SSH_KEY_BEGIN_PATTERN.forEach(pattern => {
44
+ if (pattern.test(replacedContent)) {
45
+ isBeginPartExist = true;
46
+ replacedContent = replacedContent.replace(new RegExp(pattern, 'g'), '');
47
+ }
48
+ });
49
+
50
+ SSH_KEY_END_PATTERN.forEach(pattern => {
51
+ if (pattern.test(replacedContent)) {
52
+ isEndPartExist = true;
53
+ replacedContent = replacedContent.replace(new RegExp(pattern, 'g'), '');
54
+ }
55
+ });
56
+
57
+ return { isError: !(isBeginPartExist && isEndPartExist), content: replacedContent };
58
+ };
56
59
 
57
- // Проверка по MIME type (более надежный способ)
58
- const isValidMimeType = DEFAULT_ALLOWED_MIME_TYPES.some(
59
- allowedMime => mimeType.includes(allowedMime) || allowedMime.includes(mimeType),
60
- );
60
+ const checkIsSshKeyError = (value: string) => {
61
+ const { isError, content: base64content } = removePEMBoundaries(value);
61
62
 
62
- // Файл должен пройти хотя бы одну проверку
63
- if (!isValidMimeType) {
64
- throw new Error(
65
- `INVALID_MIME_TYPE: Неподходящий тип файла. MIME: ${mimeType}, расширение: ${fileExtension || 'нет'}. ` +
66
- `Разрешенные MIME types: ${DEFAULT_ALLOWED_MIME_TYPES.join(', ')}, `,
67
- );
63
+ if (isError) {
64
+ return true;
68
65
  }
69
- };
70
66
 
71
- export const validateFileSize = (file: File): void => {
72
- if (file.size > MAX_FILE_SIZE) {
73
- throw new Error(
74
- `FILE_TOO_LARGE: Файл слишком большой. Размер: ${(file.size / 1024).toFixed(2)}KB, ` +
75
- `максимальный: ${MAX_FILE_SIZE / 1024}KB`,
76
- );
77
- }
67
+ const base64Regexp = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[+/=])[A-Za-z0-9+/=\r\n]+$/;
78
68
 
79
- // Минимальный размер для SSH ключа (примерно 100 байт)
80
- const minFileSize = 100;
81
- if (file.size < minFileSize) {
82
- throw new Error(`INVALID_FILE_TYPE: Файл слишком маленький для SSH ключа. Минимальный размер: ${minFileSize} байт`);
83
- }
69
+ return !base64Regexp.test(base64content);
84
70
  };
71
+
72
+ export const validateSshKeyErrors = (value: string) => ({
73
+ binaryChars: checkIsBinaryCharsInContent(value),
74
+ emptyFile: checkIsEmptyContent(value),
75
+ invalidSSHKey: checkIsSshKeyError(value),
76
+ });
@@ -1,2 +0,0 @@
1
- export type FileErrorType = 'INVALID_EXTENSION' | 'INVALID_MIME_TYPE' | 'FILE_TOO_LARGE' | 'INVALID_FILE_TYPE' | 'READ_ERROR' | 'INVALID_SSH_KEY' | 'EMPTY_FILE' | 'BINARY_DATA' | 'UNKNOWN_ERROR';
2
- export declare const getFileErrorType: (error: unknown) => FileErrorType;
@@ -1,32 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getFileErrorType = void 0;
4
- const getFileErrorType = (error) => {
5
- if (error instanceof Error) {
6
- const [errorType] = error.message.split(': ');
7
- switch (errorType) {
8
- case 'INVALID_EXTENSION':
9
- case 'INVALID_MIME_TYPE':
10
- return 'INVALID_EXTENSION';
11
- case 'FILE_TOO_LARGE':
12
- return 'FILE_TOO_LARGE';
13
- case 'INVALID_FILE_TYPE':
14
- return 'INVALID_EXTENSION';
15
- case 'READ_ERROR':
16
- return 'READ_ERROR';
17
- case 'INVALID_SSH_KEY':
18
- // Проверяем специфичные типы ошибок SSH ключа
19
- if (error.message.includes('пустой') || error.message.includes('empty')) {
20
- return 'EMPTY_FILE';
21
- }
22
- if (error.message.includes('бинарные') || error.message.includes('binary')) {
23
- return 'BINARY_DATA';
24
- }
25
- return 'INVALID_SSH_KEY';
26
- default:
27
- return 'UNKNOWN_ERROR';
28
- }
29
- }
30
- return 'UNKNOWN_ERROR';
31
- };
32
- exports.getFileErrorType = getFileErrorType;
@@ -1,2 +0,0 @@
1
- export type FileErrorType = 'INVALID_EXTENSION' | 'INVALID_MIME_TYPE' | 'FILE_TOO_LARGE' | 'INVALID_FILE_TYPE' | 'READ_ERROR' | 'INVALID_SSH_KEY' | 'EMPTY_FILE' | 'BINARY_DATA' | 'UNKNOWN_ERROR';
2
- export declare const getFileErrorType: (error: unknown) => FileErrorType;
@@ -1,28 +0,0 @@
1
- export const getFileErrorType = (error) => {
2
- if (error instanceof Error) {
3
- const [errorType] = error.message.split(': ');
4
- switch (errorType) {
5
- case 'INVALID_EXTENSION':
6
- case 'INVALID_MIME_TYPE':
7
- return 'INVALID_EXTENSION';
8
- case 'FILE_TOO_LARGE':
9
- return 'FILE_TOO_LARGE';
10
- case 'INVALID_FILE_TYPE':
11
- return 'INVALID_EXTENSION';
12
- case 'READ_ERROR':
13
- return 'READ_ERROR';
14
- case 'INVALID_SSH_KEY':
15
- // Проверяем специфичные типы ошибок SSH ключа
16
- if (error.message.includes('пустой') || error.message.includes('empty')) {
17
- return 'EMPTY_FILE';
18
- }
19
- if (error.message.includes('бинарные') || error.message.includes('binary')) {
20
- return 'BINARY_DATA';
21
- }
22
- return 'INVALID_SSH_KEY';
23
- default:
24
- return 'UNKNOWN_ERROR';
25
- }
26
- }
27
- return 'UNKNOWN_ERROR';
28
- };
@@ -1,41 +0,0 @@
1
- export type FileErrorType =
2
- | 'INVALID_EXTENSION'
3
- | 'INVALID_MIME_TYPE'
4
- | 'FILE_TOO_LARGE'
5
- | 'INVALID_FILE_TYPE'
6
- | 'READ_ERROR'
7
- | 'INVALID_SSH_KEY'
8
- | 'EMPTY_FILE'
9
- | 'BINARY_DATA'
10
- | 'UNKNOWN_ERROR';
11
-
12
- export const getFileErrorType = (error: unknown): FileErrorType => {
13
- if (error instanceof Error) {
14
- const [errorType] = error.message.split(': ');
15
-
16
- switch (errorType as FileErrorType) {
17
- case 'INVALID_EXTENSION':
18
- case 'INVALID_MIME_TYPE':
19
- return 'INVALID_EXTENSION';
20
- case 'FILE_TOO_LARGE':
21
- return 'FILE_TOO_LARGE';
22
- case 'INVALID_FILE_TYPE':
23
- return 'INVALID_EXTENSION';
24
- case 'READ_ERROR':
25
- return 'READ_ERROR';
26
- case 'INVALID_SSH_KEY':
27
- // Проверяем специфичные типы ошибок SSH ключа
28
- if (error.message.includes('пустой') || error.message.includes('empty')) {
29
- return 'EMPTY_FILE';
30
- }
31
- if (error.message.includes('бинарные') || error.message.includes('binary')) {
32
- return 'BINARY_DATA';
33
- }
34
- return 'INVALID_SSH_KEY';
35
- default:
36
- return 'UNKNOWN_ERROR';
37
- }
38
- }
39
-
40
- return 'UNKNOWN_ERROR';
41
- };