--- a/src/eric7/Utilities/PasswordChecker.py Fri Jan 05 16:04:03 2024 +0100 +++ b/src/eric7/Utilities/PasswordChecker.py Sat Jan 06 15:21:02 2024 +0100 @@ -7,26 +7,37 @@ Module implementing a checker for password strength. """ +import enum import re +class PasswordStrength(enum.IntEnum): + """ + Class defining the password strength. + """ + + VeryWeak = 0 + Weak = 1 + Good = 2 + Strong = 3 + VeryStrong = 4 + + +class PasswordCheckStatus(enum.Enum): + """ + Class defining the status of a password check. + """ + + Failed = 0 + Passed = 1 + Exceeded = 2 + + class PasswordChecker: """ Class implementing a checker for password strength. """ - # TODO: change this to an enum - Complexity_VeryWeak = 0 - Complexity_Weak = 1 - Complexity_Good = 2 - Complexity_Strong = 3 - Complexity_VeryStrong = 4 - - # TODO: change this to an enum - Status_Failed = 0 - Status_Passed = 1 - Status_Exceeded = 2 - def __init__(self): """ Constructor @@ -36,7 +47,7 @@ # complexity index self.complexity = { "limits": [20, 50, 60, 80, 100], - "value": self.Complexity_VeryWeak, + "value": PasswordStrength.VeryWeak, } # check categories follow @@ -45,7 +56,7 @@ self.passwordLength = { "count": 0, "minimum": 6, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": 0.5, # per character bonus "bonus": 10, # minimum reached? Get a bonus. @@ -56,7 +67,7 @@ self.recommendedPasswordLength = { "count": 0, "minimum": 8, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": 1.2, "bonus": 10, @@ -72,7 +83,7 @@ self.basicRequirements = { "count": 0, "minimum": 3, # have to be matched to get the bonus - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": 1.0, "bonus": 10, @@ -87,7 +98,7 @@ # default to start "permitted": 2.0, # 2 means, in average every character # can occur twice - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, } @@ -95,7 +106,7 @@ self.uppercaseLetters = { "count": 0, "minimum": 1, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": 0.0, "bonus": 10, @@ -106,7 +117,7 @@ self.lowercaseLetters = { "count": 0, "minimum": 1, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": 0.0, "bonus": 10, @@ -117,7 +128,7 @@ self.numerics = { "count": 0, "minimum": 1, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": 0.0, "bonus": 10, @@ -128,7 +139,7 @@ self.symbols = { "count": 0, "minimum": 1, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": 0.0, "bonus": 10, @@ -139,7 +150,7 @@ self.middleSymbols = { "count": 0, "minimum": 1, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": 0.0, "bonus": 10, @@ -150,7 +161,7 @@ self.middleNumerics = { "count": 0, "minimum": 1, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": 0.0, "bonus": 10, @@ -163,7 +174,7 @@ "data": "abcdefghijklmnopqrstuvwxyz", "length": 3, "count": 0, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": -1.0, "bonus": 0, @@ -176,7 +187,7 @@ "data": "0123456789", "length": 3, "count": 0, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": -1.0, "bonus": 0, @@ -203,7 +214,7 @@ ], "length": 4, # how long is the pattern to check and blame for? "count": 0, # how many of these pattern can be found - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": -1.0, # each occurrence is punished with that factor "bonus": 0, @@ -214,7 +225,7 @@ self.repeatedSequences = { "length": 3, "count": 0, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": 0.0, "bonus": 0, @@ -225,7 +236,7 @@ self.mirroredSequences = { "length": 3, "count": 0, - "status": self.Status_Failed, + "status": PasswordCheckStatus.Failed, "rating": 0, "factor": 0.0, "bonus": 0, @@ -254,15 +265,15 @@ @param value value to check @type int - @return status (Status_Failed, Status_Passed, Status_Exceeded) - @rtype int + @return status + @rtype PasswordCheckStatus """ if value == 0: - return self.Status_Passed + return PasswordCheckStatus.Passed elif value > 0: - return self.Status_Exceeded + return PasswordCheckStatus.Exceeded else: - return self.Status_Failed + return PasswordCheckStatus.Failed def __determineBinaryStatus(self, value): """ @@ -270,13 +281,13 @@ @param value value to check @type int - @return status (Status_Failed, Status_Passed) - @rtype int + @return status + @rtype PasswordCheckStatus """ if value == 0: - return self.Status_Passed + return PasswordCheckStatus.Passed else: - return self.Status_Failed + return PasswordCheckStatus.Failed def checkPassword(self, password): """ @@ -284,10 +295,8 @@ @param password password to be checked @type str - @return indication for the password strength (Complexity_VeryWeak, - Complexity_Weak, Complexity_Good, Complexity_Strong, - Complexity_VeryStrong) - @rtype int + @return indication for the password strength + @rtype PasswordStrength """ # how long is the password? self.passwordLength["count"] = len(password) @@ -556,7 +565,7 @@ self.passwordLength["status"] = self.__determineStatus( self.passwordLength["count"] - self.passwordLength["minimum"] ) - if self.passwordLength["status"] != self.Status_Failed: + if self.passwordLength["status"] != PasswordCheckStatus.Failed: # requirement met self.basicRequirements["count"] += 1 @@ -564,7 +573,7 @@ self.uppercaseLetters["status"] = self.__determineStatus( self.uppercaseLetters["count"] - self.uppercaseLetters["minimum"] ) - if self.uppercaseLetters["status"] != self.Status_Failed: + if self.uppercaseLetters["status"] != PasswordCheckStatus.Failed: # requirement met self.basicRequirements["count"] += 1 @@ -572,7 +581,7 @@ self.lowercaseLetters["status"] = self.__determineStatus( self.lowercaseLetters["count"] - self.lowercaseLetters["minimum"] ) - if self.lowercaseLetters["status"] != self.Status_Failed: + if self.lowercaseLetters["status"] != PasswordCheckStatus.Failed: # requirement met self.basicRequirements["count"] += 1 @@ -580,7 +589,7 @@ self.numerics["status"] = self.__determineStatus( self.numerics["count"] - self.numerics["minimum"] ) - if self.numerics["status"] != self.Status_Failed: + if self.numerics["status"] != PasswordCheckStatus.Failed: # requirement met self.basicRequirements["count"] += 1 @@ -588,7 +597,7 @@ self.symbols["status"] = self.__determineStatus( self.symbols["count"] - self.symbols["minimum"] ) - if self.symbols["status"] != self.Status_Failed: + if self.symbols["status"] != PasswordCheckStatus.Failed: # requirement met self.basicRequirements["count"] += 1 @@ -596,7 +605,7 @@ self.basicRequirements["status"] = self.__determineStatus( self.basicRequirements["count"] - self.basicRequirements["minimum"] ) - if self.basicRequirements["status"] != self.Status_Failed: + if self.basicRequirements["status"] != PasswordCheckStatus.Failed: self.basicRequirements["rating"] = ( self.basicRequirements["bonus"] + self.basicRequirements["factor"] * self.basicRequirements["count"] @@ -633,7 +642,7 @@ ) # we apply them only, if the length is not awesome - if self.recommendedPasswordLength["status"] != self.Status_Exceeded: + if self.recommendedPasswordLength["status"] != PasswordCheckStatus.Exceeded: # repeatedSequences # Honor or punish the use of repeated sequences if self.repeatedSequences["count"] == 0: @@ -660,7 +669,7 @@ # apply the redundancy # is the password length requirement fulfilled? if ( - self.recommendedPasswordLength["status"] != self.Status_Exceeded + self.recommendedPasswordLength["status"] != PasswordCheckStatus.Exceeded and self.score["count"] > 0 ): # full penalty, because password is not long enough, only for @@ -678,7 +687,7 @@ # judge it for index in range(len(self.complexity["limits"])): if self.score["adjusted"] <= self.complexity["limits"][index]: - self.complexity["value"] = index + self.complexity["value"] = PasswordStrength(index) break return self.complexity["value"]