focalboard/server/services/auth/password.go
Doug Lauder 66975bdfe9
First pass linter cleanup (#603)
* first pass linter cleanup

* address review comments
2021-06-21 11:21:42 +02:00

104 lines
2.6 KiB
Go

package auth
import (
"fmt"
"strings"
"golang.org/x/crypto/bcrypt"
)
const (
PasswordMaximumLength = 64
PasswordSpecialChars = "!\"\\#$%&'()*+,-./:;<=>?@[]^_`|~" //nolint:gosec
PasswordNumbers = "0123456789"
PasswordUpperCaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
PasswordLowerCaseLetters = "abcdefghijklmnopqrstuvwxyz"
PasswordAllChars = PasswordSpecialChars + PasswordNumbers + PasswordUpperCaseLetters + PasswordLowerCaseLetters
InvalidLowercasePassword = "lowercase"
InvalidMinLengthPassword = "min-length"
InvalidMaxLengthPassword = "max-length"
InvalidNumberPassword = "number"
InvalidUppercasePassword = "uppercase"
InvalidSymbolPassword = "symbol"
)
// HashPassword generates a hash using the bcrypt.GenerateFromPassword.
func HashPassword(password string) string {
hash, err := bcrypt.GenerateFromPassword([]byte(password), 10)
if err != nil {
panic(err)
}
return string(hash)
}
// ComparePassword compares the hash.
func ComparePassword(hash, password string) bool {
if len(password) == 0 || len(hash) == 0 {
return false
}
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
type InvalidPasswordError struct {
FailingCriterias []string
}
func (ipe *InvalidPasswordError) Error() string {
return fmt.Sprintf("invalid password, failing criteria: %s", strings.Join(ipe.FailingCriterias, ", "))
}
type PasswordSettings struct {
MinimumLength int
Lowercase bool
Number bool
Uppercase bool
Symbol bool
}
func IsPasswordValid(password string, settings PasswordSettings) error {
err := &InvalidPasswordError{
FailingCriterias: []string{},
}
if len(password) < settings.MinimumLength {
err.FailingCriterias = append(err.FailingCriterias, InvalidMinLengthPassword)
}
if len(password) > PasswordMaximumLength {
err.FailingCriterias = append(err.FailingCriterias, InvalidMaxLengthPassword)
}
if settings.Lowercase {
if !strings.ContainsAny(password, PasswordLowerCaseLetters) {
err.FailingCriterias = append(err.FailingCriterias, InvalidLowercasePassword)
}
}
if settings.Uppercase {
if !strings.ContainsAny(password, PasswordUpperCaseLetters) {
err.FailingCriterias = append(err.FailingCriterias, InvalidUppercasePassword)
}
}
if settings.Number {
if !strings.ContainsAny(password, PasswordNumbers) {
err.FailingCriterias = append(err.FailingCriterias, InvalidNumberPassword)
}
}
if settings.Symbol {
if !strings.ContainsAny(password, PasswordSpecialChars) {
err.FailingCriterias = append(err.FailingCriterias, InvalidSymbolPassword)
}
}
if len(err.FailingCriterias) > 0 {
return err
}
return nil
}