forked from cs3org/reva
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
328 additions
and
19 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Enhancement: Add the password policies | ||
|
||
Add the password policies OCIS-3767 | ||
|
||
https://github.com/cs3org/reva/pull/4147 |
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package password | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"regexp" | ||
"strings" | ||
"unicode/utf8" | ||
) | ||
|
||
var _defaultSpecialCharacters = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" | ||
|
||
// Validator describes the interface providing a password Validate method | ||
type Validator interface { | ||
Validate(str string) error | ||
} | ||
|
||
// Policies represents a password validation rules | ||
type Policies struct { | ||
minCharacters int | ||
minLowerCaseCharacters int | ||
minUpperCaseCharacters int | ||
minDigits int | ||
minSpecialCharacters int | ||
allowedSpecialCharacters string | ||
digits *regexp.Regexp | ||
specialCharacters *regexp.Regexp | ||
} | ||
|
||
// NewPasswordPolicies returns a new NewPasswordPolicies instance | ||
func NewPasswordPolicies(minCharacters, minLowerCaseCharacters, minUpperCaseCharacters, minDigits, minSpecialCharacters int, | ||
allowedSpecialCharacters string) (Validator, error) { | ||
|
||
digits := regexp.MustCompile("[0-9]") | ||
if len(allowedSpecialCharacters) > 0 { | ||
_defaultSpecialCharacters = allowedSpecialCharacters | ||
} | ||
specialCharacters, err := regexp.Compile("[" + regexp.QuoteMeta(_defaultSpecialCharacters) + "]") | ||
if err != nil { | ||
return nil, err | ||
} | ||
return &Policies{ | ||
minCharacters: minCharacters, | ||
minLowerCaseCharacters: minLowerCaseCharacters, | ||
minUpperCaseCharacters: minUpperCaseCharacters, | ||
minDigits: minDigits, | ||
minSpecialCharacters: minSpecialCharacters, | ||
allowedSpecialCharacters: allowedSpecialCharacters, | ||
digits: digits, | ||
specialCharacters: specialCharacters, | ||
}, nil | ||
} | ||
|
||
// Validate implements a password validation regarding the policy | ||
func (s Policies) Validate(str string) error { | ||
var allErr error | ||
if !utf8.ValidString(str) { | ||
return fmt.Errorf("the password contains invalid characters") | ||
} | ||
err := s.validateCharacters(str) | ||
if err != nil { | ||
allErr = errors.Join(allErr, err) | ||
} | ||
err = s.validateLowerCase(str) | ||
if err != nil { | ||
allErr = errors.Join(allErr, err) | ||
} | ||
err = s.validateUpperCase(str) | ||
if err != nil { | ||
allErr = errors.Join(allErr, err) | ||
} | ||
err = s.validateDigits(str) | ||
if err != nil { | ||
allErr = errors.Join(allErr, err) | ||
} | ||
err = s.validateSpecialCharacters(str) | ||
if err != nil { | ||
allErr = errors.Join(allErr, err) | ||
} | ||
if allErr != nil { | ||
return allErr | ||
} | ||
return nil | ||
} | ||
|
||
func (s Policies) validateCharacters(str string) error { | ||
if s.count(str) < s.minCharacters { | ||
return fmt.Errorf("at least %d characters are required", s.minCharacters) | ||
} | ||
return nil | ||
} | ||
|
||
func (s Policies) validateLowerCase(str string) error { | ||
if s.countLowerCaseCharacters(str) < s.minLowerCaseCharacters { | ||
return fmt.Errorf("at least %d lowercase letters are required", s.minLowerCaseCharacters) | ||
} | ||
return nil | ||
} | ||
|
||
func (s Policies) validateUpperCase(str string) error { | ||
if s.countUpperCaseCharacters(str) < s.minUpperCaseCharacters { | ||
return fmt.Errorf("at least %d uppercase letters are required", s.minUpperCaseCharacters) | ||
} | ||
return nil | ||
} | ||
|
||
func (s Policies) validateDigits(str string) error { | ||
if s.countDigits(str) < s.minDigits { | ||
return fmt.Errorf("at least %d numbers are required", s.minDigits) | ||
} | ||
return nil | ||
} | ||
|
||
func (s Policies) validateSpecialCharacters(str string) error { | ||
if s.countSpecialCharacters(str) < s.minSpecialCharacters { | ||
return fmt.Errorf("at least %d special characters are required. %s", s.minSpecialCharacters, s.allowedSpecialCharacters) | ||
} | ||
return nil | ||
} | ||
|
||
func (s Policies) count(str string) int { | ||
return utf8.RuneCount([]byte(str)) | ||
} | ||
|
||
func (s Policies) countLowerCaseCharacters(str string) int { | ||
var count int | ||
for _, c := range str { | ||
if strings.ToLower(string(c)) == string(c) && strings.ToUpper(string(c)) != string(c) { | ||
count++ | ||
} | ||
} | ||
return count | ||
} | ||
|
||
func (s Policies) countUpperCaseCharacters(str string) int { | ||
var count int | ||
for _, c := range str { | ||
if strings.ToUpper(string(c)) == string(c) && strings.ToLower(string(c)) != string(c) { | ||
count++ | ||
} | ||
} | ||
return count | ||
} | ||
|
||
func (s Policies) countDigits(str string) int { | ||
return len(s.digits.FindAllStringIndex(str, -1)) | ||
} | ||
|
||
func (s Policies) countSpecialCharacters(str string) int { | ||
res := s.specialCharacters.FindAllStringIndex(str, -1) | ||
return len(res) | ||
} |
Oops, something went wrong.