Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add isStrongPassword method #1348

Merged
merged 23 commits into from
Nov 19, 2020
Merged

Conversation

tbeeck
Copy link
Contributor

@tbeeck tbeeck commented Jun 7, 2020

For issue #1145
This adds the isStrongPassword method. It does include tests for when returning true/false, but not for when returning the score due to issues with test design decried here: #1145 (comment)

I am open to suggestions on how the passwords are scored since this algorithm is pretty rudimentary.

This is my first contribution to a public project, please let me know if there is anything else I can change to make this better :)

Checklist

  • PR contains only changes related; no stray files, etc.
  • README updated (where applicable)
  • Tests written (where applicable)

@profnandaa
Copy link
Member

@rubiin @tux-tn -- can review this one here please?

Copy link
Member

@tux-tn tux-tn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good to me. Great job @door-bell 🎉
I have two comments:

  • I think Readme is missing default values for strongThreshold and score
  • Since there is no standard defined for a strong password. I think the validator is a little biased. Generally validators are based on norms, standards or definitions but here this is not the case. I'm not saying that this validator is a bad thing but I think we should rather let the user choose his own definition rather than create a custom scoring system

@tbeeck
Copy link
Contributor Author

tbeeck commented Jun 11, 2020

@tux-tn Yeah, I agree that the validator is biased and won't necessarily meet the user's expectations every time. I implemented the scoring system since it was suggested in the feature request #1145 .

Do you think it would be helpful to allow the user to pass in a list of requirements like this as an optional usage?

let requirements = {
     minCharCount = 8,
     mustContainUpper = true,
     mustContainNumber = true,
     mustContainSymbol = true
}

I will hold off on fixing readme just in case we want to change things further, but I'll be sure to update that as well.

@rubiin
Copy link
Member

rubiin commented Jun 11, 2020

@tux-tn Yeah, I agree that the validator is biased and won't necessarily meet the user's expectations every time. I implemented the scoring system since it was suggested in the feature request #1145 .

Do you think it would be helpful to allow the user to pass in a list of requirements like this as an optional usage?

let requirements = {
     minCharCount = 8,
     mustContainUpper = true,
     mustContainNumber = true,
     mustContainSymbol = true
}

I will hold off on fixing readme just in case we want to change things further, but I'll be sure to update that as well.

passing options looks good plus it gives user some customizability on the parameters values

@tbeeck
Copy link
Contributor Author

tbeeck commented Jun 11, 2020

Now the user can decide to check the password by score or by requirements with these defaults specified:

const defaultRequirementOptions = {
  minLength: 8,
  minLowercase: 1,
  minUppercase: 1,
  minNumbers: 1,
  minSymbols: 1,
};

const defaultScoringOptions = {
  returnScore: false,
  pointsPerUnique: 1,
  pointsPerRepeat: 0.5,
  pointsForContainingLower: 10,
  pointsForContainingUpper: 10,
  pointsForContainingNumber: 10,
  pointsForContainingSymbol: 10,
  minStrongScore: 50,
};

isStrongPassword defaults to checking based on requirements. To use the scoring system, the user needs to use the named parameter scoringOptions.
Not sure if this is an optimal design, I am open to other suggestions.

@tbeeck
Copy link
Contributor Author

tbeeck commented Jun 29, 2020

After some more consideration I decided to change how the options work. Now there is a single options parameter with these defaults:

const defaultOptions = {
  minLength: 8,
  minLowercase: 1,
  minUppercase: 1,
  minNumbers: 1,
  minSymbols: 1,
  returnScore: false,
  pointsPerUnique: 1,
  pointsPerRepeat: 0.5,
  pointsForContainingLower: 10,
  pointsForContainingUpper: 10,
  pointsForContainingNumber: 10,
  pointsForContainingSymbol: 10,
};

The user simply decides if they want a score or not using returnScore. Otherwise it defaults to returning a boolean based on the minimum requirements for the password. This seems like a more intuitive usage to me, and the user can still test the password against a minimum score on their own. (Also, sorry this PR got messy with commits, I had some trouble syncing my remote branches across two machines)

@profnandaa
Copy link
Member

@door-bell -- I'm sorry for my delayed response on this; this sounds good to me. Are you available for any further review comments this week so that we land this with the November release?

/cc. @tux-tn @ezkemboi

Copy link
Member

@profnandaa profnandaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This LGTM for the most part. I like the flexibility in scoring!

@tbeeck
Copy link
Contributor Author

tbeeck commented Nov 15, 2020

@profnandaa Yep I'm available for any more comments!

@profnandaa
Copy link
Member

@tux-tn @rubiin @ezkemboi -- please have a look.

@ezkemboi
Copy link
Member

ezkemboi commented Nov 17, 2020

Looks good here @profnandaa but I need to confirm something on percentage scoring.
A minute I test out locally.

Copy link
Member

@ezkemboi ezkemboi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally good work.

'EXAMPLE of very long_password123!',
'mxH_+2vs&54_+H3P',
'+&DxJ=X7-4L8jRCD',
'etV*p%Nr6w&H%FeF',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a need for tests that pass returnScore as an option

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the tests for this case in the sanitizers.js test file since with this option, the function essentially becomes a sanitizer, turning the string into a number. Hope that makes sense

README.md Outdated
@@ -150,6 +150,7 @@ Validator | Description
**isSurrogatePair(str)** | check if the string contains any surrogate pairs chars.
**isUppercase(str)** | check if the string is uppercase.
**isSlug** | Check if the string is of type slug. `Options` allow a single hyphen between string. e.g. [`cn-cn`, `cn-c-c`]
**isStrongPassword(str, requirementOptions?, scoringOptions?)** | Check if a password is strong or not. Allows for custom requirements or scoring rules. If `returnScore` is true, then the function returns an integer score for the password rather than a boolean.<br/>Default options: <br/>`{ minLength: 8, minLowercase: 1, minUppercase: 1, minNumbers: 1, minSymbols: 1, returnScore: false, pointsPerUnique: 1, pointsPerRepeat: 0.5, pointsForContainingLower: 10, pointsForContainingUpper: 10, pointsForContainingNumber: 10, pointsForContainingSymbol: 10 }`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my look of the eye, I thought, I needed to pass 3 parameters, though 2 are optional.
But, from function arguments call, it takes str & option.
I expected something like below...

isStrongPassword(str [, options])

It is not a priority but my suggestion for consistency and easy readability/usage.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed this, thanks!

@profnandaa
Copy link
Member

@door-bell -- you can address Ez's comments and we land this soonest. We would like to make a release this Friday.

@tbeeck
Copy link
Contributor Author

tbeeck commented Nov 17, 2020

Travis job stuck in the queue D: However I pushed some changes to address those comments and this should be good to go

@codecov
Copy link

codecov bot commented Nov 18, 2020

Codecov Report

❗ No coverage uploaded for pull request base (master@a3cddc1). Click here to learn what that means.
The diff coverage is n/a.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #1348   +/-   ##
=========================================
  Coverage          ?   99.92%           
=========================================
  Files             ?       97           
  Lines             ?     1332           
  Branches          ?        0           
=========================================
  Hits              ?     1331           
  Misses            ?        1           
  Partials          ?        0           

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update a3cddc1...8ab1d36. Read the comment docs.

Copy link
Member

@profnandaa profnandaa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, once again, thanks for your contrib! 🎉

@profnandaa profnandaa merged commit 27aa419 into validatorjs:master Nov 19, 2020
@rubiin
Copy link
Member

rubiin commented Nov 19, 2020

@profnandaa when will the next release be available

@profnandaa
Copy link
Member

profnandaa commented Nov 23, 2020 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants