Skip to content

Instantly share code, notes, and snippets.

@fractaledmind
Created October 27, 2023 15:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fractaledmind/1fd207efaadde064ee6d75f571c16512 to your computer and use it in GitHub Desktop.
Save fractaledmind/1fd207efaadde064ee6d75f571c16512 to your computer and use it in GitHub Desktop.
<form action="#">
<section data-controller="passphrase">
<label for="passphrase-for-registration">Passphrase</label>
<input type="text"
id="passphrase-for-registration"
data-passphrase-registration-target="input"
data-action="passphrase#validate"
autocomplete="new-password"
required
minlength="12"
pattern="^(?=.*[a-z].*[a-z])(?=.*[A-Z].*[A-Z])(?=.*[0-9].*[0-9])(?=.*[!@#$%^&*_=+-].*[!@#$%^&*_=+-]).+$">
<div class="requirements">
<p>Passphrase must contain:</p>
<ul>
<li data-passphrase-target="lengthValidation">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<path id="valid" d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
<g id="invalid">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
<path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/>
</g>
</defs>
<use href="#invalid" fill="red" />
</svg>
<span>At least 12 characters</span>
</li>
<li data-passphrase-target="lowercaseValidation">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<path id="valid" d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
<g id="invalid">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
<path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/>
</g>
</defs>
<use href="#invalid" fill="red" />
</svg>
<span>At least two lowercase letters <code>(a...z)</code></span>
</li>
<li data-passphrase-target="uppercaseValidation">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<path id="valid" d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
<g id="invalid">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
<path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/>
</g>
</defs>
<use href="#invalid" fill="red" />
</svg>
<span>At least two uppercase letters <code>(A...Z)</code></span>
</li>
<li data-passphrase-target="numericalValidation">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<path id="valid" d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
<g id="invalid">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
<path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/>
</g>
</defs>
<use href="#invalid" fill="red" />
</svg>
<span>At least two numbers <code>(0...9)</code></span>
</li>
<li data-passphrase-target="characterValidation">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
<defs>
<path id="valid" d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z"/>
<g id="invalid">
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
<path d="M7.002 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 4.995z"/>
</g>
</defs>
<use href="#invalid" fill="red" />
</svg>
<span>At least two special characters <code>(!@#$%^&*_=+-)</code></span>
</li>
</ul>
</div>
</section>
<button type="submit">Submit</button>
</form>
class PassphraseController extends Stimulus.Controller {
static get targets() {
return [
"lengthValidation",
"lowercaseValidation",
"uppercaseValidation",
"numericalValidation",
"characterValidation",
"encryptedPrivateKey"
]
}
validate(event) {
const input = event.currentTarget
const minlength = parseInt(input.getAttribute('minlength'))
const pattern = input.getAttribute('pattern')
// => "^(?=.*[a-z].*[a-z])(?=.*[A-Z].*[A-Z])(?=.*[0-9].*[0-9])(?=.*[!@#$%^&*_=+-].*[!@#$%^&*_=+-]).+$"
const validations = pattern.match(/\(\?\=.*?\)/g)
// => ["(?=.*[a-z].*[a-z])", "(?=.*[A-Z].*[A-Z])", "(?=.*[0-9].*[0-9])", "(?=.*[!@#$%^&*_=+-].*[!@#$%^&*_=+-])"]
const lowercaseValidation = validations.find(v => v.includes('[a-z]'))
const uppercaseValidation = validations.find(v => v.includes('[A-Z]'))
const numericalValidation = validations.find(v => v.includes('[0-9]'))
const characterValidation = validations.find(v => v.includes('[!@#$%^&*_=+-]'))
this.#validateLength(input, minlength)
this.#validateLowercase(input, lowercaseValidation)
this.#validateUppercase(input, uppercaseValidation)
this.#validateNumerical(input, numericalValidation)
this.#validateCharacter(input, characterValidation)
}
#validateLength(input, minlength) {
const validationIcon = this.lengthValidationTarget.querySelector("svg use")
if (input.value.length >= minlength) {
validationIcon.setAttribute("href", "#valid")
validationIcon.setAttribute("fill", "green")
} else {
validationIcon.setAttribute("href", "#invalid")
validationIcon.setAttribute("fill", "red")
}
}
#validateLowercase(input, pattern) {
const regexp = new RegExp(pattern + ".+")
const validationIcon = this.lowercaseValidationTarget.querySelector("svg use")
if (regexp.test(input.value)) {
validationIcon.setAttribute("href", "#valid")
validationIcon.setAttribute("fill", "green")
} else {
validationIcon.setAttribute("href", "#invalid")
validationIcon.setAttribute("fill", "red")
}
}
#validateUppercase(input, pattern) {
const regexp = new RegExp(pattern + ".+")
const validationIcon = this.uppercaseValidationTarget.querySelector("svg use")
if (regexp.test(input.value)) {
validationIcon.setAttribute("href", "#valid")
validationIcon.setAttribute("fill", "green")
} else {
validationIcon.setAttribute("href", "#invalid")
validationIcon.setAttribute("fill", "red")
}
}
#validateNumerical(input, pattern) {
const regexp = new RegExp(pattern + ".+")
const validationIcon = this.numericalValidationTarget.querySelector("svg use")
if (regexp.test(input.value)) {
validationIcon.setAttribute("href", "#valid")
validationIcon.setAttribute("fill", "green")
} else {
validationIcon.setAttribute("href", "#invalid")
validationIcon.setAttribute("fill", "red")
}
}
#validateCharacter(input, pattern) {
const regexp = new RegExp(pattern + ".+")
const validationIcon = this.characterValidationTarget.querySelector("svg use")
if (regexp.test(input.value)) {
validationIcon.setAttribute("href", "#valid")
validationIcon.setAttribute("fill", "green")
} else {
validationIcon.setAttribute("href", "#invalid")
validationIcon.setAttribute("fill", "red")
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment