diff --git a/auth/auth.go b/auth/auth.go new file mode 100644 index 0000000..643ef67 --- /dev/null +++ b/auth/auth.go @@ -0,0 +1,50 @@ +package auth + +import ( + "errors" + "io/ioutil" + "log" + + "golang.org/x/crypto/bcrypt" +) + +type AuthStore interface { + Register(user, pass string) error + Authenticate(user, pass string) error + Remove(user string) error +} + +type Htpasswd struct { + accounts map[string]string + filePath string +} + +func NewHtpasswd(path string) (AuthStore, error) { + _, err := ioutil.ReadFile(path) + if err != nil { + return Htpasswd{}, err + } + return Htpasswd{}, nil +} + +func (s Htpasswd) Register(user, pass string) (err error) { + s.accounts[user], err = hash(pass) + if err != nil { + return + } + log.Println(s.accounts[user]) + return +} + +func (s Htpasswd) Authenticate(user, pass string) (err error) { + return errors.New("work in progress") +} + +func (s Htpasswd) Remove(user string) (err error) { + return errors.New("work in progress") +} + +func hash(pass string) (string, error) { + output, err := bcrypt.GenerateFromPassword([]byte(pass), bcrypt.DefaultCost) + return string(output), err +} diff --git a/auth/auth_test.go b/auth/auth_test.go new file mode 100644 index 0000000..1cb14e7 --- /dev/null +++ b/auth/auth_test.go @@ -0,0 +1,54 @@ +package auth + +import ( + "fmt" + "io/ioutil" + "strings" + "testing" +) + +type User struct { + user string + pass string + hashed string +} + +func TestHtpasswdSuccess(t *testing.T) { + path := "/tmp/.htpasswd" + user1 := User{ + user: "user", + pass: "password", + hashed: "$2a$14$SQSscaF4fVO3e5dp2/.VPuVQDPKqxSagLQnN6OncTRtoQw0ie9ByK", + } + err := ioutil.WriteFile(path, + []byte(fmt.Sprintf("%s:%s", user1.user, user1.hashed)), 0640) + if err != nil { + t.Fatal(err) + } + store, err := NewHtpasswd(path) + if err != nil { + t.Fatal(err) + } + err = store.Authenticate(user1.user, user1.pass) + if err != nil { + t.Error(err) + } + + user2 := User{ + user: "foo", + pass: "bar", + } + err = store.Register(user2.user, user2.pass) + if err != nil { + t.Error(err) + } + data, err := ioutil.ReadFile(path) + if err != nil { + t.Error(err) + } + for _, u := range []User{user1, user2} { + if !strings.Contains(string(data), u.user) { + t.Errorf("%s not found in htpasswd file: %s", u.user, string(data)) + } + } +} diff --git a/go.mod b/go.mod index db3b5ca..ff8c9c7 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module github.com/lancatlin/ledger-quicknote go 1.19 + +require golang.org/x/crypto v0.1.0 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..37c516a --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=