-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpassword_validator.go
77 lines (63 loc) · 1.69 KB
/
password_validator.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
// Copyright 2021 Hyperscale. All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
package validator
import (
"fmt"
"math"
"reflect"
"unicode"
)
// Password config options.
type Password struct {
Min int
Max int
RequiredRangeTable map[string][]*unicode.RangeTable
}
type passwordValidator struct {
opts Password
}
// NewPasswordValidator constructor.
func NewPasswordValidator(opts Password) Validator {
if opts.Max == 0 {
opts.Max = math.MaxInt64
}
if len(opts.RequiredRangeTable) == 0 {
opts.RequiredRangeTable = map[string][]*unicode.RangeTable{
"upper case": {unicode.Upper, unicode.Title},
"lower case": {unicode.Lower},
"numeric": {unicode.Number, unicode.Digit},
"special": {unicode.Space, unicode.Symbol, unicode.Punct, unicode.Mark},
}
}
return &passwordValidator{
opts: opts,
}
}
func (v passwordValidator) Validate(input interface{}) error {
switch val := input.(type) {
case string:
size := len(val)
if size < v.opts.Min {
return fmt.Errorf("the password is less than %d characters long", v.opts.Min)
}
if size > v.opts.Max {
return fmt.Errorf("the password is more than %d characters long", v.opts.Max)
}
return v.checkPassword(val)
default:
return fmt.Errorf("invalid \"%s\" type given. String expected", reflect.TypeOf(val))
}
}
func (v passwordValidator) checkPassword(password string) error {
next:
for name, classes := range v.opts.RequiredRangeTable {
for _, r := range password {
if unicode.IsOneOf(classes, r) {
continue next
}
}
return fmt.Errorf("the password must have at least one %s character", name)
}
return nil
}