Files
services/password/handler/password.go
2022-03-02 17:09:45 +00:00

81 lines
1.6 KiB
Go

package handler
import (
"context"
"crypto/rand"
"strings"
pb "github.com/micro/services/password/proto"
)
const (
minLength = 8
special = "!@#$%&*"
numbers = "0123456789"
lowercase = "abcdefghijklmnopqrstuvwxyz"
uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
allChars = special + numbers + lowercase + uppercase
)
func random(chars string, i int) string {
bytes := make([]byte, i)
rand.Read(bytes)
for i, b := range bytes {
bytes[i] = chars[b%byte(len(chars))]
}
return string(bytes)
}
type Password struct{}
func (p *Password) Generate(ctx context.Context, req *pb.GenerateRequest, rsp *pb.GenerateResponse) error {
if req.Length <= 0 {
req.Length = int32(minLength)
}
charSpace := ""
if req.Numbers {
charSpace += numbers
}
if req.Lowercase {
charSpace += lowercase
}
if req.Uppercase {
charSpace += uppercase
}
if req.Special {
charSpace += special
}
if len(charSpace) == 0 {
charSpace = allChars
}
for {
// generate and return password
rsp.Password = random(charSpace, int(req.Length))
// validate we have minimums needed
reqsSatisfied := true
if req.Numbers {
reqsSatisfied = reqsSatisfied && strings.ContainsAny(rsp.Password, numbers)
}
if req.Lowercase {
reqsSatisfied = reqsSatisfied && strings.ContainsAny(rsp.Password, lowercase)
}
if req.Uppercase {
reqsSatisfied = reqsSatisfied && strings.ContainsAny(rsp.Password, uppercase)
}
if req.Special {
reqsSatisfied = reqsSatisfied && strings.ContainsAny(rsp.Password, special)
}
if reqsSatisfied {
break
}
// failed to satisfy all reqs, try again
}
return nil
}