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
7 changed files
with
336 additions
and
15 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
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,167 @@ | ||
package password | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
"regexp" | ||
"strings" | ||
"unicode/utf8" | ||
) | ||
|
||
var defaultSpecialCharacters = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" | ||
|
||
type Validator interface { | ||
Validate(str string) error | ||
} | ||
|
||
type Policies struct { | ||
minCharacters int | ||
minLowerCaseCharacters int | ||
minUpperCaseCharacters int | ||
minDigits int | ||
minSpecialCharacters int | ||
allowedSpecialCharacters string | ||
digits *regexp.Regexp | ||
specialCharacters *regexp.Regexp | ||
} | ||
|
||
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 | ||
} | ||
|
||
func NewDefaultPasswordPolicies() (Validator, error) { | ||
return NewPasswordPolicies(0, 0, 0, 0, 0, "") | ||
} | ||
|
||
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 { | ||
if s.minCharacters == 1 { | ||
return fmt.Errorf("at least one character is required") | ||
} | ||
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 { | ||
if s.minLowerCaseCharacters == 1 { | ||
return fmt.Errorf("at least one lowercase letter is required") | ||
} | ||
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 { | ||
if s.minUpperCaseCharacters == 1 { | ||
return fmt.Errorf("at least one uppercase letter is required") | ||
} | ||
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 { | ||
if s.minDigits == 1 { | ||
return fmt.Errorf("at least one number is required") | ||
} | ||
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 { | ||
if s.minSpecialCharacters == 1 { | ||
return fmt.Errorf("at least one special character is required. %s", s.allowedSpecialCharacters) | ||
} | ||
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.