unjs / magic-regexp

A compiled-away, type-safe, readable RegExp alternative

Home Page:https://regexp.dev

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

how do i recreate a password requirements regex?

majkl-zumberi opened this issue · comments

📚 Is your documentation request related to a problem?

i'm trying to recreate a password requirements regex like the following:
password must contains al least 8 characters, one lowercase character, one uppercase char, one digit and one special character (! @ # $ % ^ & *)

const PASSWORD_RE= createRegExp(
  (
    oneOrMore(letter.lowercase).times.atLeast(1)
  .and(oneOrMore(letter.uppercase).times.atLeast(1))
  .and(oneOrMore(digit))
  .and(
    oneOrMore(
      charIn('!')
      .or(charIn('@'))
      .or(charIn('#'))
      .or(charIn('$'))
      .or(charIn('%'))
      .or(charIn('^'))
      .or(charIn('&'))
      .or(charIn('*'))
      ).times.atLeast(1)
    )
  )
.times.atLeast(8),['g']
)

i tried to paste the generated regex in one of the regex tester like regex101
but seems to not working as expected

the documentation seems lacking in terms of providing a fully understandable examples

can you help me to achieve a working password regex? Where am I doing wrong?

🔍 Where should you find it?

No response

ℹ️ Additional context

No response

You can do something like this:

const PASSWORD_RE = createRegExp(
  exactly('')
    .before(char.times.any().and(letter.lowercase))
    .before(char.times.any().and(letter.uppercase))
    .before(char.times.any().and(digit))
    .before(char.times.any().and(charIn('!@#$%^&*')))
    .and(letter.or(digit.or(charIn('!@#$%^&*'))).times.atLeast(8))
    .at.lineStart()
    .at.lineEnd()
)

charIn can just take all characters in one go as a string, but we do still missing Input helper that create custom range(s) to simplify more, ex: for regexp [b-t3-6]

thanks @didavid61202 for your solution, i'll end up closing the issue
but let me first ask you to briefly explain how you ended up with this solution
why there's the need of exactly('')? and .at.lineStart() .at.lineEnd() what they do?

the documentation as i mentioned before isn't that clear

@didavid61202
your solution create regex ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%\^&*])(?:[a-zA-Z]|(?:\d|[!@#$%\^&*])){8,}$
how to create more clear regex like ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%\^&*]).{8,}$

Hi, just as an aside, "hard" password requirements are actually counter-productive, as a security measure.

For the purpose of checking the safety of a password, you would be better served by something like https://github.com/dropbox/zxcvbn

Nonetheless, have fun with regular expressions!

@didavid61202 your solution create regex ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%\^&*])(?:[a-zA-Z]|(?:\d|[!@#$%\^&*])){8,}$ how to create more clear regex like ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%\^&*]).{8,}$

maybe

const regexp = createRegExp(
    exactly(
      exactly('')
        .before(char.times.any().and(letter.lowercase))
        .before(char.times.any().and(letter.uppercase))
        .before(char.times.any().and(digit))
        .before(char.times.any().and(charIn('!@#$%^&*'))),
      char
        .times.atLeast(8),
    )
      .at.lineStart()
      .at.lineEnd()
)