Created
January 20, 2026 09:01
-
-
Save jdboachie/72e88c96abd8199878b9d915f6c803ca to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| interface ValidationResult { | |
| passed: boolean; | |
| violations: string[] | null; | |
| } | |
| type ValidatorFn = (input: string) => ValidationResult; | |
| const validators: ValidatorFn[] = []; | |
| const isDigit = (char: string) => { | |
| return char >= "0" && char <= "9"; | |
| }; | |
| const isLower = (char: string) => { | |
| return char >= "a" && char <= "z"; | |
| }; | |
| function registerValidators(validatorFns: ValidatorFn[]) { | |
| for (const fn of validatorFns) { | |
| validators.push(fn); | |
| } | |
| } | |
| function hasOnlyOneColon(input: string): ValidationResult { | |
| const passed = input.split(":").length == 2; | |
| return { | |
| passed, | |
| violations: passed ? null : ["Missing or multiple separators"], | |
| }; | |
| } | |
| function validateUsername(input: string): ValidationResult { | |
| try { | |
| let splits = input.split(":"); | |
| if (!(splits.length === 2)) { | |
| throw new Error(); | |
| } | |
| input = splits[0] ?? ""; | |
| } catch { | |
| return { passed: false, violations: null }; | |
| } | |
| let passed: boolean = true; | |
| let violations: string[] = []; | |
| if (input.length < 5 || input.length > 15) { | |
| passed = false; | |
| violations.push("Username length/format error"); | |
| } | |
| if (isDigit(input[0]!) || isDigit(input[-1]!)) { | |
| passed = false; | |
| violations.push("Username length/format error"); | |
| return { | |
| passed, | |
| violations, | |
| }; | |
| } | |
| for (const char of input) { | |
| if (!isLower(char) && !isDigit(char)) { | |
| passed = false; | |
| violations.push("Username length/format error"); | |
| break; | |
| } | |
| } | |
| return { | |
| passed, | |
| violations, | |
| }; | |
| } | |
| function validatePassword(input: string): ValidationResult { | |
| try { | |
| let splits = input.split(":"); | |
| if (!(splits.length === 2)) { | |
| throw new Error(); | |
| } | |
| input = splits[1] ?? ""; | |
| } catch { | |
| return { passed: false, violations: null }; | |
| } | |
| let passed: boolean = true; | |
| let violations: string[] = []; | |
| if (input.length < 8) { | |
| passed = false; | |
| violations.push("Password complexity error"); | |
| return { | |
| passed, | |
| violations, | |
| }; | |
| } | |
| let hasUppercaseChar = false; | |
| let hasLowercaseChar = false; | |
| let hasDigit = false; | |
| let hasSpecialChar = false; | |
| for (const char of input) { | |
| if (isDigit(char)) { | |
| hasDigit = true; | |
| } else if (isLower(char)) { | |
| hasLowercaseChar = true; | |
| } else if (char >= "A" && char <= "Z") { | |
| hasUppercaseChar = true; | |
| } else if (["!", "@", "#", "$"].includes(char)) { | |
| hasSpecialChar = true; | |
| } | |
| } | |
| passed = hasUppercaseChar && hasLowercaseChar && hasDigit && hasSpecialChar; | |
| if (!passed) { | |
| violations.push("Password complexity error") | |
| } | |
| return { | |
| passed, | |
| violations, | |
| }; | |
| } | |
| registerValidators([hasOnlyOneColon, validateUsername, validatePassword]); | |
| function validateCredentials(input: string) { | |
| let passed: boolean = true; | |
| let violations: string[] = []; | |
| for (const v of validators) { | |
| let res = v(input); | |
| passed = passed ? res.passed : passed; | |
| if (res.violations) { | |
| violations.push(...res.violations); | |
| } | |
| } | |
| console.log(passed ? "Secure" : "Insecure"); | |
| if (!passed) { | |
| console.log("Reasons:", violations.join(", ")); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment