@mudrichenkoevgeny/web-platform-sdk-core-security 0.0.1 → 0.1.2
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.
- package/LICENSE +201 -201
- package/README.md +110 -110
- package/dist/di/security-component.d.ts +56 -0
- package/dist/di/security-component.d.ts.map +1 -0
- package/dist/di/security-component.test.d.ts +2 -0
- package/dist/di/security-component.test.d.ts.map +1 -0
- package/dist/error/model/security-error.d.ts +117 -0
- package/dist/error/model/security-error.d.ts.map +1 -0
- package/dist/error/model/security-error.test.d.ts +2 -0
- package/dist/error/model/security-error.test.d.ts.map +1 -0
- package/dist/error/parser/security-error-parser.d.ts +37 -0
- package/dist/error/parser/security-error-parser.d.ts.map +1 -0
- package/dist/error/parser/security-error-parser.test.d.ts +2 -0
- package/dist/error/parser/security-error-parser.test.d.ts.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11946 -4898
- package/dist/integration/SecuritySettingsIntegration.test.d.ts +2 -0
- package/dist/integration/SecuritySettingsIntegration.test.d.ts.map +1 -0
- package/dist/mock/di/security-component-mock.d.ts +9 -0
- package/dist/mock/di/security-component-mock.d.ts.map +1 -0
- package/dist/mock/network/open-security-settings-api-mock.d.ts +25 -0
- package/dist/mock/network/open-security-settings-api-mock.d.ts.map +1 -0
- package/dist/mock/repository/open-security-settings-repository-mock.d.ts +28 -0
- package/dist/mock/repository/open-security-settings-repository-mock.d.ts.map +1 -0
- package/dist/mock/storage/open-security-settings-storage-mock.d.ts +31 -0
- package/dist/mock/storage/open-security-settings-storage-mock.d.ts.map +1 -0
- package/dist/mock/usecase/validate-password-use-case-mock.d.ts +22 -0
- package/dist/mock/usecase/validate-password-use-case-mock.d.ts.map +1 -0
- package/dist/network/api/security-settings/fetch-open-security-settings-api.d.ts +22 -0
- package/dist/network/api/security-settings/fetch-open-security-settings-api.d.ts.map +1 -0
- package/dist/network/api/security-settings/fetch-open-security-settings-api.test.d.ts +2 -0
- package/dist/network/api/security-settings/fetch-open-security-settings-api.test.d.ts.map +1 -0
- package/dist/network/api/security-settings/open-security-settings-api.d.ts +14 -0
- package/dist/network/api/security-settings/open-security-settings-api.d.ts.map +1 -0
- package/dist/network/api/security-settings/security-settings-dto-mapping.test.d.ts +2 -0
- package/dist/network/api/security-settings/security-settings-dto-mapping.test.d.ts.map +1 -0
- package/dist/network/contract/security-web-socket-event-types.d.ts +2 -0
- package/dist/network/contract/security-web-socket-event-types.d.ts.map +1 -0
- package/dist/network/websocket/message-handler/security-web-socket-message-handler.d.ts +15 -0
- package/dist/network/websocket/message-handler/security-web-socket-message-handler.d.ts.map +1 -0
- package/dist/network/websocket/message-handler/security-web-socket-message-handler.test.d.ts +2 -0
- package/dist/network/websocket/message-handler/security-web-socket-message-handler.test.d.ts.map +1 -0
- package/dist/repository/open-security-settings-repository-impl.d.ts +57 -0
- package/dist/repository/open-security-settings-repository-impl.d.ts.map +1 -0
- package/dist/repository/open-security-settings-repository-impl.test.d.ts +2 -0
- package/dist/repository/open-security-settings-repository-impl.test.d.ts.map +1 -0
- package/dist/repository/open-security-settings-repository.d.ts +35 -0
- package/dist/repository/open-security-settings-repository.d.ts.map +1 -0
- package/dist/storage/security-settings/encrypted-open-security-settings-storage.d.ts +32 -0
- package/dist/storage/security-settings/encrypted-open-security-settings-storage.d.ts.map +1 -0
- package/dist/storage/security-settings/encrypted-open-security-settings-storage.test.d.ts +2 -0
- package/dist/storage/security-settings/encrypted-open-security-settings-storage.test.d.ts.map +1 -0
- package/dist/storage/security-settings/open-security-settings-storage.d.ts +23 -0
- package/dist/storage/security-settings/open-security-settings-storage.d.ts.map +1 -0
- package/dist/usecase/observe-open-security-settings-use-case.d.ts +19 -0
- package/dist/usecase/observe-open-security-settings-use-case.d.ts.map +1 -0
- package/dist/usecase/observe-open-security-settings-use-case.test.d.ts +2 -0
- package/dist/usecase/observe-open-security-settings-use-case.test.d.ts.map +1 -0
- package/dist/usecase/refresh-open-security-settings-use-case.d.ts +22 -0
- package/dist/usecase/refresh-open-security-settings-use-case.d.ts.map +1 -0
- package/dist/usecase/refresh-open-security-settings-use-case.test.d.ts +2 -0
- package/dist/usecase/refresh-open-security-settings-use-case.test.d.ts.map +1 -0
- package/dist/usecase/validate-password-use-case.d.ts +26 -0
- package/dist/usecase/validate-password-use-case.d.ts.map +1 -0
- package/dist/usecase/validate-password-use-case.test.d.ts +2 -0
- package/dist/usecase/validate-password-use-case.test.d.ts.map +1 -0
- package/package.json +16 -7
- package/src/di/security-component.test.ts +0 -33
- package/src/di/security-component.ts +0 -86
- package/src/domain/model/open-security-settings.ts +0 -79
- package/src/domain/model/password-policy-validator.test.ts +0 -96
- package/src/domain/model/password-policy-validator.ts +0 -63
- package/src/error/model/security-error.test.ts +0 -65
- package/src/error/model/security-error.ts +0 -182
- package/src/error/naming/client-security-error-codes.ts +0 -21
- package/src/error/parser/security-error-parser.test.ts +0 -87
- package/src/error/parser/security-error-parser.ts +0 -138
- package/src/index.ts +0 -24
- package/src/locales/en/strings.ts +0 -67
- package/src/locales/index.ts +0 -2
- package/src/locales/ru/strings.ts +0 -35
- package/src/mock/di/security-component-mock.ts +0 -35
- package/src/mock/domain/model/open-security-settings-mock.ts +0 -52
- package/src/mock/network/model/open-security-settings-payload-mock.ts +0 -28
- package/src/mock/network/open-security-settings-api-mock.ts +0 -38
- package/src/mock/repository/open-security-settings-repository-mock.ts +0 -62
- package/src/mock/storage/open-security-settings-storage-mock.ts +0 -45
- package/src/mock/usecase/validate-password-use-case-mock.ts +0 -31
- package/src/network/contract/security-web-socket-event-types.ts +0 -7
- package/src/network/security-settings/fetch-open-security-settings-api.test.ts +0 -51
- package/src/network/security-settings/fetch-open-security-settings-api.ts +0 -30
- package/src/network/security-settings/open-security-settings-api.ts +0 -15
- package/src/network/websocket/message-handler/security-web-socket-message-handler.test.ts +0 -19
- package/src/network/websocket/message-handler/security-web-socket-message-handler.ts +0 -19
- package/src/repository/open-security-settings-repository-impl.test.ts +0 -112
- package/src/repository/open-security-settings-repository-impl.ts +0 -151
- package/src/repository/open-security-settings-repository.ts +0 -39
- package/src/storage/security-settings/encrypted-open-security-settings-storage.test.ts +0 -71
- package/src/storage/security-settings/encrypted-open-security-settings-storage.ts +0 -65
- package/src/storage/security-settings/open-security-settings-storage.ts +0 -25
- package/src/usecase/refresh-open-security-settings-use-case.ts +0 -26
- package/src/usecase/security-use-cases.test.ts +0 -67
- package/src/usecase/validate-password-use-case.ts +0 -76
- package/tsconfig.json +0 -16
- package/vite.config.ts +0 -50
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest'
|
|
2
|
-
import { SecurityErrorCodes, SecurityErrorArgs, CommonErrorArgs } from '@mudrichenkoevgeny/shared-foundation'
|
|
3
|
-
import { CommonError } from '@mudrichenkoevgeny/web-platform-sdk-core-common'
|
|
4
|
-
import type { ErrorId } from "@mudrichenkoevgeny/web-platform-sdk-core-common";
|
|
5
|
-
import { SecurityErrorParser } from '@/error/parser/security-error-parser'
|
|
6
|
-
import { SecurityError } from '@/error/model/security-error'
|
|
7
|
-
import { enSecurityStrings, ruSecurityStrings } from '@/locales/index'
|
|
8
|
-
describe('SecurityErrorParser', () => {
|
|
9
|
-
const parserEn = new SecurityErrorParser(enSecurityStrings)
|
|
10
|
-
const parserRu = new SecurityErrorParser(ruSecurityStrings)
|
|
11
|
-
|
|
12
|
-
it('parses client password policy validation errors', () => {
|
|
13
|
-
expect(parserEn.parse(SecurityError.passwordPolicyUnavailable())).toBe(
|
|
14
|
-
'Failed to load password requirements. Please try again.'
|
|
15
|
-
)
|
|
16
|
-
expect(parserEn.parse(SecurityError.passwordTooShort(10))).toBe(
|
|
17
|
-
'Password must be at least 10 characters long.'
|
|
18
|
-
)
|
|
19
|
-
expect(parserEn.parse(SecurityError.passwordNoLetter())).toBe(
|
|
20
|
-
'Password must contain at least one letter.'
|
|
21
|
-
)
|
|
22
|
-
expect(parserEn.parse(SecurityError.passwordNoUpperCase())).toBe(
|
|
23
|
-
'Password must contain at least one uppercase letter.'
|
|
24
|
-
)
|
|
25
|
-
expect(parserEn.parse(SecurityError.passwordNoLowerCase())).toBe(
|
|
26
|
-
'Password must contain at least one lowercase letter.'
|
|
27
|
-
)
|
|
28
|
-
expect(parserEn.parse(SecurityError.passwordNoDigit())).toBe(
|
|
29
|
-
'Password must contain at least one digit.'
|
|
30
|
-
)
|
|
31
|
-
expect(parserEn.parse(SecurityError.passwordNoSpecialChar())).toBe(
|
|
32
|
-
'Password must contain at least one special character.'
|
|
33
|
-
)
|
|
34
|
-
expect(parserEn.parse(SecurityError.passwordTooCommon())).toBe(
|
|
35
|
-
'Password is too common and insecure.'
|
|
36
|
-
)
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('supports dynamic language getter function for reactive localizations', () => {
|
|
40
|
-
let currentLanguage = enSecurityStrings
|
|
41
|
-
const dynamicParser = new SecurityErrorParser(() => currentLanguage)
|
|
42
|
-
|
|
43
|
-
expect(dynamicParser.parse(SecurityError.passwordTooShort(8))).toBe(
|
|
44
|
-
'Password must be at least 8 characters long.'
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
currentLanguage = ruSecurityStrings
|
|
48
|
-
|
|
49
|
-
expect(dynamicParser.parse(SecurityError.passwordTooShort(8))).toBe(
|
|
50
|
-
'Пароль должен содержать не менее 8 символов.'
|
|
51
|
-
)
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
it('parses shared foundation security error codes', () => {
|
|
55
|
-
const mfaError = {
|
|
56
|
-
id: 'err-1' as ErrorId,
|
|
57
|
-
code: SecurityErrorCodes.MFA_CONFIRMATION_REQUIRED,
|
|
58
|
-
args: { [SecurityErrorArgs.MFA_TOKEN]: 'token-123' },
|
|
59
|
-
isRetryable: false
|
|
60
|
-
} as const
|
|
61
|
-
|
|
62
|
-
expect(parserEn.parse(mfaError)).toBe('Authentication confirmation is required. MFA token: token-123')
|
|
63
|
-
expect(parserRu.parse(mfaError)).toBe('Требуется подтверждение аутентификации. Токен MFA: token-123')
|
|
64
|
-
|
|
65
|
-
const otpError = {
|
|
66
|
-
id: 'err-2' as ErrorId,
|
|
67
|
-
code: SecurityErrorCodes.OTP_RETRY_TOO_SOON,
|
|
68
|
-
args: { [CommonErrorArgs.RETRY_AFTER_SECONDS]: '60' },
|
|
69
|
-
isRetryable: true
|
|
70
|
-
} as const
|
|
71
|
-
|
|
72
|
-
expect(parserEn.parse(otpError)).toBe('Too many attempts. Please try again in 60 seconds.')
|
|
73
|
-
|
|
74
|
-
const totpAlreadyEnabled = {
|
|
75
|
-
id: 'err-3' as ErrorId,
|
|
76
|
-
code: SecurityErrorCodes.TOTP_ALREADY_ENABLED,
|
|
77
|
-
args: null,
|
|
78
|
-
isRetryable: false
|
|
79
|
-
} as const
|
|
80
|
-
|
|
81
|
-
expect(parserEn.parse(totpAlreadyEnabled)).toBe('Two-factor authentication is already enabled for this account.')
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
it('returns null for unhandled non-security error codes', () => {
|
|
85
|
-
expect(parserEn.parse(CommonError.unknown())).toBeNull()
|
|
86
|
-
})
|
|
87
|
-
})
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
SecurityErrorCodes,
|
|
3
|
-
SecurityErrorArgs,
|
|
4
|
-
CommonErrorArgs
|
|
5
|
-
} from '@mudrichenkoevgeny/shared-foundation'
|
|
6
|
-
import type { AppError, AppErrorParser } from '@mudrichenkoevgeny/web-platform-sdk-core-common'
|
|
7
|
-
import { ClientSecurityErrorCodes } from '@/error/naming/client-security-error-codes'
|
|
8
|
-
import { enSecurityStrings } from '@/locales/index'
|
|
9
|
-
import type { CoreSecurityStrings } from "@/locales/index";
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* AppErrorParser implementation for security-domain error codes.
|
|
13
|
-
*/
|
|
14
|
-
export class SecurityErrorParser implements AppErrorParser {
|
|
15
|
-
private readonly getStrings: () => CoreSecurityStrings
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Constructs a new {@link SecurityErrorParser}.
|
|
19
|
-
*
|
|
20
|
-
* @param stringsOrGetter - Core security strings dictionary or dynamic getter function returning current strings
|
|
21
|
-
*/
|
|
22
|
-
public constructor(
|
|
23
|
-
stringsOrGetter: CoreSecurityStrings | (() => CoreSecurityStrings) = enSecurityStrings
|
|
24
|
-
) {
|
|
25
|
-
this.getStrings = typeof stringsOrGetter === 'function' ? stringsOrGetter : () => stringsOrGetter
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Parses security domain errors into localized string messages.
|
|
30
|
-
*
|
|
31
|
-
* @param appError - Application error instance
|
|
32
|
-
* @returns Localized string message or null if code is unhandled by this parser
|
|
33
|
-
*/
|
|
34
|
-
public parse(appError: AppError): string | null {
|
|
35
|
-
const args = appError.args ?? {}
|
|
36
|
-
const strings = this.getStrings()
|
|
37
|
-
|
|
38
|
-
switch (appError.code) {
|
|
39
|
-
case SecurityErrorCodes.MFA_CONFIRMATION_REQUIRED:
|
|
40
|
-
return this.resolveLocalizedString(
|
|
41
|
-
args,
|
|
42
|
-
SecurityErrorArgs.MFA_TOKEN,
|
|
43
|
-
(mfaToken) => strings.error_security_mfa_confirmation_required_args(mfaToken),
|
|
44
|
-
strings.error_security_mfa_confirmation_required
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
case SecurityErrorCodes.OTP_RETRY_TOO_SOON:
|
|
48
|
-
return this.resolveLocalizedString(
|
|
49
|
-
args,
|
|
50
|
-
CommonErrorArgs.RETRY_AFTER_SECONDS,
|
|
51
|
-
(seconds) => strings.error_security_otp_retry_too_soon_args(seconds),
|
|
52
|
-
strings.error_security_otp_retry_too_soon
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
case SecurityErrorCodes.PASSWORD_TOO_WEAK: {
|
|
56
|
-
if (Object.keys(args).length === 0) {
|
|
57
|
-
return strings.error_security_password_too_weak
|
|
58
|
-
}
|
|
59
|
-
return strings.error_security_password_too_weak_args(
|
|
60
|
-
args[SecurityErrorArgs.PASSWORD_FAIL_TOO_SHORT] ?? 'false',
|
|
61
|
-
args[SecurityErrorArgs.PASSWORD_MIN_LENGTH] ?? '0',
|
|
62
|
-
args[SecurityErrorArgs.PASSWORD_FAIL_NO_LETTER] ?? 'false',
|
|
63
|
-
args[SecurityErrorArgs.PASSWORD_FAIL_NO_UPPERCASE] ?? 'false',
|
|
64
|
-
args[SecurityErrorArgs.PASSWORD_FAIL_NO_LOWERCASE] ?? 'false',
|
|
65
|
-
args[SecurityErrorArgs.PASSWORD_FAIL_NO_DIGIT] ?? 'false',
|
|
66
|
-
args[SecurityErrorArgs.PASSWORD_FAIL_NO_SPECIAL_CHAR] ?? 'false',
|
|
67
|
-
args[SecurityErrorArgs.PASSWORD_FAIL_TOO_COMMON] ?? 'false'
|
|
68
|
-
)
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
case SecurityErrorCodes.TOTP_ALREADY_ENABLED:
|
|
72
|
-
return strings.error_security_totp_already_enabled
|
|
73
|
-
|
|
74
|
-
case SecurityErrorCodes.TOTP_NOT_ENABLED:
|
|
75
|
-
return strings.error_security_totp_not_enabled
|
|
76
|
-
|
|
77
|
-
case SecurityErrorCodes.MFA_TOKEN_EXPIRED:
|
|
78
|
-
return strings.error_security_mfa_token_expired
|
|
79
|
-
|
|
80
|
-
case SecurityErrorCodes.RECOVERY_CODE_ALREADY_USED:
|
|
81
|
-
return strings.error_security_recovery_code_used
|
|
82
|
-
|
|
83
|
-
case SecurityErrorCodes.INVALID_TOTP_CODE:
|
|
84
|
-
return strings.error_security_invalid_totp_code
|
|
85
|
-
|
|
86
|
-
case SecurityErrorCodes.INVALID_MFA_TOKEN:
|
|
87
|
-
return strings.error_security_invalid_mfa_token
|
|
88
|
-
|
|
89
|
-
case SecurityErrorCodes.IP_NOT_ALLOWED:
|
|
90
|
-
return strings.error_security_ip_not_allowed
|
|
91
|
-
|
|
92
|
-
case ClientSecurityErrorCodes.PASSWORD_POLICY_UNAVAILABLE:
|
|
93
|
-
return strings.error_security_password_policy_unavailable
|
|
94
|
-
|
|
95
|
-
case ClientSecurityErrorCodes.PASSWORD_TOO_SHORT:
|
|
96
|
-
return this.resolveLocalizedString(
|
|
97
|
-
args,
|
|
98
|
-
SecurityErrorArgs.PASSWORD_MIN_LENGTH,
|
|
99
|
-
(minLength) => strings.error_security_password_too_short_args(minLength),
|
|
100
|
-
strings.error_security_password_too_short
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
case ClientSecurityErrorCodes.PASSWORD_NO_LETTER:
|
|
104
|
-
return strings.error_security_password_no_letter
|
|
105
|
-
|
|
106
|
-
case ClientSecurityErrorCodes.PASSWORD_NO_UPPERCASE:
|
|
107
|
-
return strings.error_security_password_no_uppercase
|
|
108
|
-
|
|
109
|
-
case ClientSecurityErrorCodes.PASSWORD_NO_LOWERCASE:
|
|
110
|
-
return strings.error_security_password_no_lowercase
|
|
111
|
-
|
|
112
|
-
case ClientSecurityErrorCodes.PASSWORD_NO_DIGIT:
|
|
113
|
-
return strings.error_security_password_no_digit
|
|
114
|
-
|
|
115
|
-
case ClientSecurityErrorCodes.PASSWORD_NO_SPECIAL_CHAR:
|
|
116
|
-
return strings.error_security_password_no_special_char
|
|
117
|
-
|
|
118
|
-
case ClientSecurityErrorCodes.PASSWORD_TOO_COMMON:
|
|
119
|
-
return strings.error_security_password_too_common
|
|
120
|
-
|
|
121
|
-
default:
|
|
122
|
-
return null
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
private resolveLocalizedString(
|
|
127
|
-
args: Record<string, string>,
|
|
128
|
-
key: string,
|
|
129
|
-
withArgsFormatter: (value: string) => string,
|
|
130
|
-
fallback: string
|
|
131
|
-
): string {
|
|
132
|
-
const value = args[key]
|
|
133
|
-
if (value && value.trim().length > 0) {
|
|
134
|
-
return withArgsFormatter(value)
|
|
135
|
-
}
|
|
136
|
-
return fallback
|
|
137
|
-
}
|
|
138
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export * from './locales/index.js'
|
|
2
|
-
export * from './error/naming/client-security-error-codes.js'
|
|
3
|
-
export * from './error/model/security-error.js'
|
|
4
|
-
export * from './error/parser/security-error-parser.js'
|
|
5
|
-
export * from './domain/model/open-security-settings.js'
|
|
6
|
-
export * from './domain/model/password-policy-validator.js'
|
|
7
|
-
export * from './storage/security-settings/open-security-settings-storage.js'
|
|
8
|
-
export * from './storage/security-settings/encrypted-open-security-settings-storage.js'
|
|
9
|
-
export * from './network/security-settings/open-security-settings-api.js'
|
|
10
|
-
export * from './network/security-settings/fetch-open-security-settings-api.js'
|
|
11
|
-
export * from './network/contract/security-web-socket-event-types.js'
|
|
12
|
-
export * from './network/websocket/message-handler/security-web-socket-message-handler.js'
|
|
13
|
-
export * from './repository/open-security-settings-repository.js'
|
|
14
|
-
export * from './repository/open-security-settings-repository-impl.js'
|
|
15
|
-
export * from './usecase/refresh-open-security-settings-use-case.js'
|
|
16
|
-
export * from './usecase/validate-password-use-case.js'
|
|
17
|
-
export * from './di/security-component.js'
|
|
18
|
-
export * from './mock/domain/model/open-security-settings-mock.js'
|
|
19
|
-
export * from './mock/network/model/open-security-settings-payload-mock.js'
|
|
20
|
-
export * from './mock/network/open-security-settings-api-mock.js'
|
|
21
|
-
export * from './mock/repository/open-security-settings-repository-mock.js'
|
|
22
|
-
export * from './mock/storage/open-security-settings-storage-mock.js'
|
|
23
|
-
export * from './mock/usecase/validate-password-use-case-mock.js'
|
|
24
|
-
export * from './mock/di/security-component-mock.js'
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
export interface CoreSecurityStrings {
|
|
2
|
-
error_security_mfa_confirmation_required: string
|
|
3
|
-
error_security_mfa_confirmation_required_args: (mfaToken: string) => string
|
|
4
|
-
error_security_totp_already_enabled: string
|
|
5
|
-
error_security_totp_not_enabled: string
|
|
6
|
-
error_security_mfa_token_expired: string
|
|
7
|
-
error_security_invalid_mfa_token: string
|
|
8
|
-
error_security_invalid_totp_code: string
|
|
9
|
-
error_security_recovery_code_used: string
|
|
10
|
-
error_security_otp_retry_too_soon: string
|
|
11
|
-
error_security_otp_retry_too_soon_args: (seconds: string | number) => string
|
|
12
|
-
error_security_password_too_weak: string
|
|
13
|
-
error_security_password_too_weak_args: (
|
|
14
|
-
tooShort: boolean | string,
|
|
15
|
-
minLength: string | number,
|
|
16
|
-
noLetters: boolean | string,
|
|
17
|
-
noUppercase: boolean | string,
|
|
18
|
-
noLowercase: boolean | string,
|
|
19
|
-
noDigits: boolean | string,
|
|
20
|
-
noSpecialChars: boolean | string,
|
|
21
|
-
tooCommon: boolean | string
|
|
22
|
-
) => string
|
|
23
|
-
error_security_password_policy_unavailable: string
|
|
24
|
-
error_security_password_too_short: string
|
|
25
|
-
error_security_password_too_short_args: (minLength: string | number) => string
|
|
26
|
-
error_security_password_no_letter: string
|
|
27
|
-
error_security_password_no_uppercase: string
|
|
28
|
-
error_security_password_no_lowercase: string
|
|
29
|
-
error_security_password_no_digit: string
|
|
30
|
-
error_security_password_no_special_char: string
|
|
31
|
-
error_security_password_too_common: string
|
|
32
|
-
error_security_ip_not_allowed: string
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const enSecurityStrings: CoreSecurityStrings = {
|
|
36
|
-
error_security_mfa_confirmation_required: 'Authentication confirmation is required.',
|
|
37
|
-
error_security_mfa_confirmation_required_args: (mfaToken: string) => `Authentication confirmation is required. MFA token: ${mfaToken}`,
|
|
38
|
-
error_security_totp_already_enabled: 'Two-factor authentication is already enabled for this account.',
|
|
39
|
-
error_security_totp_not_enabled: 'Two-factor authentication is not enabled for this account.',
|
|
40
|
-
error_security_mfa_token_expired: 'The MFA token has expired. Please request a new one.',
|
|
41
|
-
error_security_invalid_mfa_token: 'The MFA token is invalid or malformed.',
|
|
42
|
-
error_security_invalid_totp_code: 'The provided code is invalid.',
|
|
43
|
-
error_security_recovery_code_used: 'This recovery code has already been used.',
|
|
44
|
-
error_security_otp_retry_too_soon: 'Too many attempts. Please try again later.',
|
|
45
|
-
error_security_otp_retry_too_soon_args: (seconds: string | number) => `Too many attempts. Please try again in ${seconds} seconds.`,
|
|
46
|
-
error_security_password_too_weak: 'Password is too weak.',
|
|
47
|
-
error_security_password_too_weak_args: (
|
|
48
|
-
tooShort: boolean | string,
|
|
49
|
-
minLength: string | number,
|
|
50
|
-
noLetters: boolean | string,
|
|
51
|
-
noUppercase: boolean | string,
|
|
52
|
-
noLowercase: boolean | string,
|
|
53
|
-
noDigits: boolean | string,
|
|
54
|
-
noSpecialChars: boolean | string,
|
|
55
|
-
tooCommon: boolean | string
|
|
56
|
-
) => `Password is too weak. Too short: ${tooShort} (min: ${minLength}), No letters: ${noLetters}, No uppercase: ${noUppercase}, No lowercase: ${noLowercase}, No digits: ${noDigits}, No special chars: ${noSpecialChars}, Too common: ${tooCommon}.`,
|
|
57
|
-
error_security_password_policy_unavailable: 'Failed to load password requirements. Please try again.',
|
|
58
|
-
error_security_password_too_short: 'Password is too short.',
|
|
59
|
-
error_security_password_too_short_args: (minLength: string | number) => `Password must be at least ${minLength} characters long.`,
|
|
60
|
-
error_security_password_no_letter: 'Password must contain at least one letter.',
|
|
61
|
-
error_security_password_no_uppercase: 'Password must contain at least one uppercase letter.',
|
|
62
|
-
error_security_password_no_lowercase: 'Password must contain at least one lowercase letter.',
|
|
63
|
-
error_security_password_no_digit: 'Password must contain at least one digit.',
|
|
64
|
-
error_security_password_no_special_char: 'Password must contain at least one special character.',
|
|
65
|
-
error_security_password_too_common: 'Password is too common and insecure.',
|
|
66
|
-
error_security_ip_not_allowed: 'Request was rejected because the client IP address is not permitted.'
|
|
67
|
-
}
|
package/src/locales/index.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import type { CoreSecurityStrings } from '@/locales/en/strings'
|
|
2
|
-
|
|
3
|
-
export const ruSecurityStrings: CoreSecurityStrings = {
|
|
4
|
-
error_security_mfa_confirmation_required: 'Требуется подтверждение аутентификации.',
|
|
5
|
-
error_security_mfa_confirmation_required_args: (mfaToken: string) => `Требуется подтверждение аутентификации. Токен MFA: ${mfaToken}`,
|
|
6
|
-
error_security_totp_already_enabled: 'Двухфакторная аутентификация уже включена для этого аккаунта.',
|
|
7
|
-
error_security_totp_not_enabled: 'Двухфакторная аутентификация не включена для этого аккаунта.',
|
|
8
|
-
error_security_mfa_token_expired: 'Срок действия токена MFA истек. Запросите новый.',
|
|
9
|
-
error_security_invalid_mfa_token: 'Токен MFA недействителен.',
|
|
10
|
-
error_security_invalid_totp_code: 'Указанный код недействителен.',
|
|
11
|
-
error_security_recovery_code_used: 'Этот код восстановления уже был использован.',
|
|
12
|
-
error_security_otp_retry_too_soon: 'Слишком много попыток. Пожалуйста, попробуйте позже.',
|
|
13
|
-
error_security_otp_retry_too_soon_args: (seconds: string | number) => `Слишком много попыток. Повторите через ${seconds} сек.`,
|
|
14
|
-
error_security_password_too_weak: 'Пароль слишком слабый.',
|
|
15
|
-
error_security_password_too_weak_args: (
|
|
16
|
-
tooShort: boolean | string,
|
|
17
|
-
minLength: string | number,
|
|
18
|
-
noLetters: boolean | string,
|
|
19
|
-
noUppercase: boolean | string,
|
|
20
|
-
noLowercase: boolean | string,
|
|
21
|
-
noDigits: boolean | string,
|
|
22
|
-
noSpecialChars: boolean | string,
|
|
23
|
-
tooCommon: boolean | string
|
|
24
|
-
) => `Пароль слишком слабый. Слишком короткий: ${tooShort} (мин: ${minLength}), Нет букв: ${noLetters}, Нет заглавных: ${noUppercase}, Нет строчных: ${noLowercase}, Нет цифр: ${noDigits}, Нет спецсимволов: ${noSpecialChars}, Слишком распространенный: ${tooCommon}.`,
|
|
25
|
-
error_security_password_policy_unavailable: 'Не удалось загрузить требования к паролю.',
|
|
26
|
-
error_security_password_too_short: 'Пароль слишком короткий.',
|
|
27
|
-
error_security_password_too_short_args: (minLength: string | number) => `Пароль должен содержать не менее ${minLength} символов.`,
|
|
28
|
-
error_security_password_no_letter: 'Пароль должен содержать хотя бы одну букву.',
|
|
29
|
-
error_security_password_no_uppercase: 'Пароль должен содержать хотя бы одну заглавную букву.',
|
|
30
|
-
error_security_password_no_lowercase: 'Пароль должен содержать хотя бы одну строчную букву.',
|
|
31
|
-
error_security_password_no_digit: 'Пароль должен содержать хотя бы одну цифру.',
|
|
32
|
-
error_security_password_no_special_char: 'Пароль должен содержать хотя бы один специальный символ.',
|
|
33
|
-
error_security_password_too_common: 'Пароль слишком распространен и ненадежен.',
|
|
34
|
-
error_security_ip_not_allowed: 'Запрос отклонен, так как IP-адрес не разрешен политикой безопасности.'
|
|
35
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { SecurityComponent } from '@/di/security-component'
|
|
2
|
-
import type { SecurityComponentConfig } from '@/di/security-component'
|
|
3
|
-
import {
|
|
4
|
-
WebSocketServiceMock,
|
|
5
|
-
HttpClient,
|
|
6
|
-
EncryptedSettingsMock,
|
|
7
|
-
DeviceInfoProviderMock
|
|
8
|
-
} from '@mudrichenkoevgeny/web-platform-sdk-core-common'
|
|
9
|
-
import { OpenSecuritySettingsApiMock } from '@/mock/network/open-security-settings-api-mock'
|
|
10
|
-
import { OpenSecuritySettingsStorageMock } from '@/mock/storage/open-security-settings-storage-mock'
|
|
11
|
-
/**
|
|
12
|
-
* Creates a pre-configured {@link SecurityComponent} instance for testing and Storybook preview purposes.
|
|
13
|
-
*
|
|
14
|
-
* @param config - Optional configuration overrides for the mock component
|
|
15
|
-
* @returns Fully initialized {@link SecurityComponent}
|
|
16
|
-
*/
|
|
17
|
-
export const createMockSecurityComponent = (
|
|
18
|
-
config?: Partial<SecurityComponentConfig>
|
|
19
|
-
): SecurityComponent => {
|
|
20
|
-
const ws = config?.webSocketService ?? new WebSocketServiceMock()
|
|
21
|
-
const httpClient = config?.httpClient ?? new HttpClient({
|
|
22
|
-
baseUrl: 'https://api.example.com',
|
|
23
|
-
deviceInfoProvider: new DeviceInfoProviderMock()
|
|
24
|
-
})
|
|
25
|
-
const encryptedSettings = config?.encryptedSettings ?? new EncryptedSettingsMock()
|
|
26
|
-
|
|
27
|
-
return new SecurityComponent({
|
|
28
|
-
webSocketService: ws,
|
|
29
|
-
httpClient,
|
|
30
|
-
encryptedSettings,
|
|
31
|
-
openSecuritySettingsApi: config?.openSecuritySettingsApi ?? new OpenSecuritySettingsApiMock(),
|
|
32
|
-
openSecuritySettingsStorage: config?.openSecuritySettingsStorage ?? new OpenSecuritySettingsStorageMock(),
|
|
33
|
-
passwordPolicyValidator: config?.passwordPolicyValidator
|
|
34
|
-
})
|
|
35
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
OpenPasswordPolicy,
|
|
3
|
-
OtpConfirmation,
|
|
4
|
-
OpenSecuritySettings
|
|
5
|
-
} from '@/domain/model/open-security-settings'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Creates a mock {@link OpenPasswordPolicy} object.
|
|
9
|
-
*
|
|
10
|
-
* @param overrides - Optional property overrides
|
|
11
|
-
* @returns Mock open password policy instance
|
|
12
|
-
*/
|
|
13
|
-
export const openPasswordPolicyMock = (
|
|
14
|
-
overrides?: Partial<OpenPasswordPolicy>
|
|
15
|
-
): OpenPasswordPolicy => ({
|
|
16
|
-
minLength: 8,
|
|
17
|
-
requireLetter: true,
|
|
18
|
-
requireUpperCase: true,
|
|
19
|
-
requireLowerCase: true,
|
|
20
|
-
requireDigit: true,
|
|
21
|
-
requireSpecialChar: true,
|
|
22
|
-
...overrides
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Creates a mock {@link OtpConfirmation} object.
|
|
27
|
-
*
|
|
28
|
-
* @param overrides - Optional property overrides
|
|
29
|
-
* @returns Mock OTP confirmation instance
|
|
30
|
-
*/
|
|
31
|
-
export const otpConfirmationMock = (
|
|
32
|
-
overrides?: Partial<OtpConfirmation>
|
|
33
|
-
): OtpConfirmation => ({
|
|
34
|
-
retryAfterSeconds: 60,
|
|
35
|
-
numberOfSymbols: 6,
|
|
36
|
-
expirationSeconds: 300,
|
|
37
|
-
...overrides
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Creates a mock {@link OpenSecuritySettings} object.
|
|
42
|
-
*
|
|
43
|
-
* @param overrides - Optional property overrides for child objects
|
|
44
|
-
* @returns Mock open security settings instance
|
|
45
|
-
*/
|
|
46
|
-
export const openSecuritySettingsMock = (overrides?: {
|
|
47
|
-
openPasswordPolicy?: Partial<OpenPasswordPolicy>
|
|
48
|
-
otpConfirmation?: Partial<OtpConfirmation>
|
|
49
|
-
}): OpenSecuritySettings => ({
|
|
50
|
-
openPasswordPolicy: openPasswordPolicyMock(overrides?.openPasswordPolicy),
|
|
51
|
-
otpConfirmation: otpConfirmationMock(overrides?.otpConfirmation)
|
|
52
|
-
})
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import type { OpenSecuritySettingsPayload } from '@mudrichenkoevgeny/shared-foundation'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Creates a mock {@link OpenSecuritySettingsPayload} matching server response structures.
|
|
5
|
-
*
|
|
6
|
-
* @param overrides - Optional property overrides
|
|
7
|
-
* @returns Mock open security settings payload
|
|
8
|
-
*/
|
|
9
|
-
export const openSecuritySettingsPayloadMock = (
|
|
10
|
-
overrides?: Partial<OpenSecuritySettingsPayload>
|
|
11
|
-
): OpenSecuritySettingsPayload => ({
|
|
12
|
-
open_password_policy: {
|
|
13
|
-
min_length: 8,
|
|
14
|
-
require_letter: true,
|
|
15
|
-
require_upper_case: true,
|
|
16
|
-
require_lower_case: true,
|
|
17
|
-
require_digit: true,
|
|
18
|
-
require_special_char: true,
|
|
19
|
-
...(overrides?.open_password_policy ?? {})
|
|
20
|
-
},
|
|
21
|
-
otp_confirmation: {
|
|
22
|
-
retry_after_seconds: 60,
|
|
23
|
-
number_of_symbols: 6,
|
|
24
|
-
expiration_seconds: 300,
|
|
25
|
-
...(overrides?.otp_confirmation ?? {})
|
|
26
|
-
},
|
|
27
|
-
...overrides
|
|
28
|
-
})
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { OpenSecuritySettingsPayload } from '@mudrichenkoevgeny/shared-foundation'
|
|
2
|
-
import { CommonError } from '@mudrichenkoevgeny/web-platform-sdk-core-common'
|
|
3
|
-
import type { AppResult, AppError } from "@mudrichenkoevgeny/web-platform-sdk-core-common";
|
|
4
|
-
import type { OpenSecuritySettingsApi } from '@/network/security-settings/open-security-settings-api'
|
|
5
|
-
import { openSecuritySettingsPayloadMock } from '@/mock/network/model/open-security-settings-payload-mock'
|
|
6
|
-
/**
|
|
7
|
-
* Mock implementation of {@link OpenSecuritySettingsApi}.
|
|
8
|
-
*/
|
|
9
|
-
export class OpenSecuritySettingsApiMock implements OpenSecuritySettingsApi {
|
|
10
|
-
public getSecuritySettingsCallCount = 0
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Constructs a new {@link OpenSecuritySettingsApiMock}.
|
|
14
|
-
*
|
|
15
|
-
* @param mockPayload - Initial mock payload to return
|
|
16
|
-
* @param shouldFail - Whether requests should return an error
|
|
17
|
-
*/
|
|
18
|
-
public constructor(
|
|
19
|
-
private readonly mockPayload?: OpenSecuritySettingsPayload,
|
|
20
|
-
private readonly shouldFail: boolean = false
|
|
21
|
-
) {}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Simulates fetching open security settings.
|
|
25
|
-
*
|
|
26
|
-
* @returns Configured mock result or error
|
|
27
|
-
*/
|
|
28
|
-
public async getSecuritySettings(): Promise<AppResult<OpenSecuritySettingsPayload, AppError>> {
|
|
29
|
-
this.getSecuritySettingsCallCount++
|
|
30
|
-
|
|
31
|
-
if (this.shouldFail) {
|
|
32
|
-
return { success: false, error: CommonError.unknown() }
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const payload = this.mockPayload ?? openSecuritySettingsPayloadMock()
|
|
36
|
-
return { success: true, data: payload }
|
|
37
|
-
}
|
|
38
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { CommonError } from '@mudrichenkoevgeny/web-platform-sdk-core-common'
|
|
2
|
-
import type { AppResult, AppError } from "@mudrichenkoevgeny/web-platform-sdk-core-common";
|
|
3
|
-
import type { OpenSecuritySettingsRepository } from '@/repository/open-security-settings-repository'
|
|
4
|
-
import type { OpenSecuritySettingsObserver } from '@/repository/open-security-settings-repository'
|
|
5
|
-
import type { OpenSecuritySettings } from '@/domain/model/open-security-settings'
|
|
6
|
-
import { openSecuritySettingsMock } from '@/mock/domain/model/open-security-settings-mock'
|
|
7
|
-
/**
|
|
8
|
-
* Configuration options for {@link OpenSecuritySettingsRepositoryMock}.
|
|
9
|
-
*/
|
|
10
|
-
export interface OpenSecuritySettingsRepositoryMockConfig {
|
|
11
|
-
/** Initial settings payload. */
|
|
12
|
-
initialSettings?: OpenSecuritySettings
|
|
13
|
-
/** If true, getter and refresh will return AppError. */
|
|
14
|
-
shouldFailGet?: boolean
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Mock implementation of {@link OpenSecuritySettingsRepository} for testing and Storybook.
|
|
19
|
-
*/
|
|
20
|
-
export class OpenSecuritySettingsRepositoryMock implements OpenSecuritySettingsRepository {
|
|
21
|
-
public refreshCallCount = 0
|
|
22
|
-
public updateCallCount = 0
|
|
23
|
-
private settings: OpenSecuritySettings
|
|
24
|
-
private shouldFailGet: boolean
|
|
25
|
-
private readonly observers = new Set<OpenSecuritySettingsObserver>()
|
|
26
|
-
|
|
27
|
-
public constructor(config?: OpenSecuritySettingsRepositoryMockConfig) {
|
|
28
|
-
this.settings = config?.initialSettings ?? openSecuritySettingsMock()
|
|
29
|
-
this.shouldFailGet = config?.shouldFailGet ?? false
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
public async getOpenSecuritySettings(): Promise<AppResult<OpenSecuritySettings, AppError>> {
|
|
33
|
-
if (this.shouldFailGet) {
|
|
34
|
-
return { success: false, error: CommonError.unknown() }
|
|
35
|
-
}
|
|
36
|
-
return { success: true, data: this.settings }
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
public async refreshOpenSecuritySettings(): Promise<AppResult<OpenSecuritySettings, AppError>> {
|
|
40
|
-
this.refreshCallCount++
|
|
41
|
-
if (this.shouldFailGet) {
|
|
42
|
-
return { success: false, error: CommonError.unknown() }
|
|
43
|
-
}
|
|
44
|
-
return { success: true, data: this.settings }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
public async updateOpenSecuritySettings(securitySettings: OpenSecuritySettings): Promise<void> {
|
|
48
|
-
this.updateCallCount++
|
|
49
|
-
this.settings = securitySettings
|
|
50
|
-
for (const obs of this.observers) {
|
|
51
|
-
obs(this.settings)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
public observeOpenSecuritySettings(observer: OpenSecuritySettingsObserver): () => void {
|
|
56
|
-
this.observers.add(observer)
|
|
57
|
-
observer(this.settings)
|
|
58
|
-
return () => {
|
|
59
|
-
this.observers.delete(observer)
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import type { OpenSecuritySettingsStorage } from '@/storage/security-settings/open-security-settings-storage'
|
|
2
|
-
import type { OpenSecuritySettings } from '@/domain/model/open-security-settings'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Mock in-memory implementation of {@link OpenSecuritySettingsStorage}.
|
|
6
|
-
*/
|
|
7
|
-
export class OpenSecuritySettingsStorageMock implements OpenSecuritySettingsStorage {
|
|
8
|
-
private settings: OpenSecuritySettings | null = null
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Constructs a new {@link OpenSecuritySettingsStorageMock}.
|
|
12
|
-
*
|
|
13
|
-
* @param initialSettings - Initial cached settings
|
|
14
|
-
*/
|
|
15
|
-
public constructor(initialSettings?: OpenSecuritySettings) {
|
|
16
|
-
if (initialSettings) {
|
|
17
|
-
this.settings = initialSettings
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Retrieves the mock stored settings.
|
|
23
|
-
*
|
|
24
|
-
* @returns Mock settings or null
|
|
25
|
-
*/
|
|
26
|
-
public async getOpenSecuritySettings(): Promise<OpenSecuritySettings | null> {
|
|
27
|
-
return this.settings
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Updates the mock stored settings.
|
|
32
|
-
*
|
|
33
|
-
* @param securitySettings - New settings
|
|
34
|
-
*/
|
|
35
|
-
public async updateOpenSecuritySettings(securitySettings: OpenSecuritySettings): Promise<void> {
|
|
36
|
-
this.settings = securitySettings
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Clears the mock stored settings.
|
|
41
|
-
*/
|
|
42
|
-
public async clearOpenSecuritySettings(): Promise<void> {
|
|
43
|
-
this.settings = null
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import type { AppResult, AppError } from '@mudrichenkoevgeny/web-platform-sdk-core-common'
|
|
2
|
-
import { ValidatePasswordUseCase } from '@/usecase/validate-password-use-case'
|
|
3
|
-
import { SecurityError } from '@/error/model/security-error'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Mock implementation of {@link ValidatePasswordUseCase} for testing UI components.
|
|
7
|
-
*/
|
|
8
|
-
export class ValidatePasswordUseCaseMock extends ValidatePasswordUseCase {
|
|
9
|
-
/**
|
|
10
|
-
* Constructs a new {@link ValidatePasswordUseCaseMock}.
|
|
11
|
-
*
|
|
12
|
-
* @param shouldFail - If true, mock will always fail with passwordTooShort
|
|
13
|
-
*/
|
|
14
|
-
public constructor(private readonly shouldFail: boolean = false) {
|
|
15
|
-
// Pass null casts to bypass constructor checks since we override the method
|
|
16
|
-
super(null as any, null as any)
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Evaluates the candidate password synchronously.
|
|
21
|
-
*
|
|
22
|
-
* @param _password - Candidate password (ignored)
|
|
23
|
-
* @returns Configured mock result
|
|
24
|
-
*/
|
|
25
|
-
public async execute(_password: string): Promise<AppResult<void, AppError>> {
|
|
26
|
-
if (this.shouldFail) {
|
|
27
|
-
return { success: false, error: SecurityError.passwordTooShort(8) }
|
|
28
|
-
}
|
|
29
|
-
return { success: true, data: undefined }
|
|
30
|
-
}
|
|
31
|
-
}
|