77 lines
1.7 KiB
Go
77 lines
1.7 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"backend/pkg/charsets"
|
|
|
|
"golang.org/x/crypto/bcrypt"
|
|
)
|
|
|
|
type PasswordUtil interface {
|
|
Hash(password string) (string, error)
|
|
Compare(password, hash string) bool
|
|
Validate(password string) error
|
|
}
|
|
|
|
func NewPasswordUtil() PasswordUtil {
|
|
specialChars := `!@#$%^&*()_-+={[}]|\:;"'<,>.?/`
|
|
return &passwordUtil{
|
|
charsetSpecialChars: charsets.NewCharsetFromString(specialChars),
|
|
}
|
|
}
|
|
|
|
type passwordUtil struct {
|
|
charsetSpecialChars charsets.Charset
|
|
}
|
|
|
|
func (b *passwordUtil) Hash(password string) (string, error) {
|
|
bytes, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
|
return string(bytes), nil
|
|
}
|
|
|
|
func (b *passwordUtil) Compare(password, hash string) bool {
|
|
return nil == bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
|
}
|
|
|
|
func (b *passwordUtil) Validate(password string) error {
|
|
if len(password) < 8 {
|
|
return fmt.Errorf("password must contain 8 or more characters")
|
|
}
|
|
|
|
charsetUpper := charsets.GetCharset(charsets.CharsetTypeLettersUpper)
|
|
charsetLower := charsets.GetCharset(charsets.CharsetTypeLettersLower)
|
|
|
|
lowercaseLettersCount := 0
|
|
uppercaseLettersCount := 0
|
|
specialCharsCount := 0
|
|
for _, v := range password {
|
|
if b.charsetSpecialChars.TestRune(v) {
|
|
specialCharsCount++
|
|
continue
|
|
}
|
|
|
|
if charsetUpper.TestRune(v) {
|
|
uppercaseLettersCount++
|
|
continue
|
|
}
|
|
|
|
if charsetLower.TestRune(v) {
|
|
lowercaseLettersCount++
|
|
continue
|
|
}
|
|
}
|
|
|
|
if lowercaseLettersCount == 0 {
|
|
return fmt.Errorf("password must contain at least 1 lowercase letter")
|
|
}
|
|
if uppercaseLettersCount == 0 {
|
|
return fmt.Errorf("password must contain at least 1 uppercase letter")
|
|
}
|
|
if specialCharsCount == 0 {
|
|
return fmt.Errorf("password must contain at least 1 special character")
|
|
}
|
|
|
|
return nil
|
|
}
|