*: remove in memory password info repo

This commit is contained in:
Eric Chiang 2016-02-09 12:57:42 -08:00
parent 2726f4dcdf
commit 72d1ecab64
13 changed files with 100 additions and 177 deletions

View file

@ -46,12 +46,19 @@ func makeTestFixtures() *testFixtures {
return repo return repo
}() }()
f.pwr = user.NewPasswordInfoRepoFromPasswordInfos([]user.PasswordInfo{ f.pwr = func() user.PasswordInfoRepo {
repo, err := db.NewPasswordInfoRepoFromPasswordInfos(dbMap, []user.PasswordInfo{
{ {
UserID: "ID-1", UserID: "ID-1",
Password: []byte("hi."), Password: []byte("hi."),
}, },
}) })
if err != nil {
panic("Failed to create user repo: " + err.Error())
}
return repo
}()
ccr := connector.NewConnectorConfigRepoFromConfigs([]connector.ConnectorConfig{ ccr := connector.NewConnectorConfigRepoFromConfigs([]connector.ConnectorConfig{
&connector.LocalConnectorConfig{ID: "local"}, &connector.LocalConnectorConfig{ID: "local"},
}) })

View file

@ -38,6 +38,16 @@ func NewPasswordInfoRepo(dbm *gorp.DbMap) user.PasswordInfoRepo {
} }
} }
func NewPasswordInfoRepoFromPasswordInfos(dbm *gorp.DbMap, infos []user.PasswordInfo) (user.PasswordInfoRepo, error) {
repo := NewPasswordInfoRepo(dbm)
for _, info := range infos {
if err := repo.Create(nil, info); err != nil {
return nil, err
}
}
return repo, nil
}
type passwordInfoRepo struct { type passwordInfoRepo struct {
dbMap *gorp.DbMap dbMap *gorp.DbMap
} }

View file

@ -5,6 +5,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/go-gorp/gorp"
"github.com/kylelemons/godebug/pretty" "github.com/kylelemons/godebug/pretty"
"github.com/coreos/dex/db" "github.com/coreos/dex/db"
@ -21,12 +22,14 @@ var (
) )
func newPasswordInfoRepo(t *testing.T) user.PasswordInfoRepo { func newPasswordInfoRepo(t *testing.T) user.PasswordInfoRepo {
var dbMap *gorp.DbMap
if os.Getenv("DEX_TEST_DSN") == "" { if os.Getenv("DEX_TEST_DSN") == "" {
return user.NewPasswordInfoRepoFromPasswordInfos(testPWs) dbMap = db.NewMemDB()
} else {
dbMap = connect(t)
} }
dbMap := connect(t) repo, err := db.NewPasswordInfoRepoFromPasswordInfos(dbMap, testPWs)
repo := db.NewPasswordInfoRepo(dbMap) if err != nil {
if err := user.LoadPasswordInfos(repo, testPWs); err != nil {
t.Fatalf("Unable to add password infos: %v", err) t.Fatalf("Unable to add password infos: %v", err)
} }
return repo return repo

View file

@ -53,7 +53,13 @@ func makeUserObjects(users []user.UserWithRemoteIdentities, passwords []user.Pas
} }
return repo return repo
}() }()
pwr := user.NewPasswordInfoRepoFromPasswordInfos(passwords) pwr := func() user.PasswordInfoRepo {
repo, err := db.NewPasswordInfoRepoFromPasswordInfos(dbMap, passwords)
if err != nil {
panic("Failed to create password info repo: " + err.Error())
}
return repo
}()
ccr := connector.NewConnectorConfigRepoFromConfigs( ccr := connector.NewConnectorConfigRepoFromConfigs(
[]connector.ConnectorConfig{&connector.LocalConnectorConfig{ID: "local"}}, []connector.ConnectorConfig{&connector.LocalConnectorConfig{ID: "local"}},

View file

@ -144,7 +144,7 @@ func TestHTTPExchangeTokenRefreshToken(t *testing.T) {
t.Fatalf("Unexpected error: %v", err) t.Fatalf("Unexpected error: %v", err)
} }
passwordInfoRepo := user.NewPasswordInfoRepo() passwordInfoRepo := db.NewPasswordInfoRepo(db.NewMemDB())
refreshTokenRepo := refreshtest.NewTestRefreshTokenRepo() refreshTokenRepo := refreshtest.NewTestRefreshTokenRepo()
srv := &server.Server{ srv := &server.Server{

View file

@ -142,7 +142,7 @@ func (cfg *SingleServerConfig) Configure(srv *Server) error {
return err return err
} }
pwiRepo := user.NewPasswordInfoRepo() pwiRepo := db.NewPasswordInfoRepo(dbMap)
refTokRepo := db.NewRefreshTokenRepo(dbMap) refTokRepo := db.NewRefreshTokenRepo(dbMap)

View file

@ -95,7 +95,10 @@ func makeTestFixtures() (*testFixtures, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
pwRepo := user.NewPasswordInfoRepoFromPasswordInfos(testPasswordInfos) pwRepo, err := db.NewPasswordInfoRepoFromPasswordInfos(dbMap, testPasswordInfos)
if err != nil {
return nil, err
}
connConfigs := []connector.ConnectorConfig{ connConfigs := []connector.ConnectorConfig{
&connector.OIDCConnectorConfig{ &connector.OIDCConnectorConfig{

2
test
View file

@ -14,7 +14,7 @@ COVER=${COVER:-"-cover"}
source ./build source ./build
TESTABLE="connector db integration pkg/crypto pkg/flag pkg/http pkg/net pkg/time pkg/html functional/repo server session session/manager user user/api user/manager email admin" TESTABLE="connector db integration pkg/crypto pkg/flag pkg/http pkg/net pkg/time pkg/html functional/repo server session session/manager user user/api user/manager user/email email admin"
FORMATTABLE="$TESTABLE cmd/dexctl cmd/dex-worker cmd/dex-overlord examples/app functional pkg/log" FORMATTABLE="$TESTABLE cmd/dexctl cmd/dex-worker cmd/dex-overlord examples/app functional pkg/log"
# user has not provided PKG override # user has not provided PKG override

View file

@ -123,7 +123,8 @@ func makeTestFixtures() (*UsersAPI, *testEmailer) {
return repo return repo
}() }()
pwr := user.NewPasswordInfoRepoFromPasswordInfos([]user.PasswordInfo{ pwr := func() user.PasswordInfoRepo {
repo, err := db.NewPasswordInfoRepoFromPasswordInfos(dbMap, []user.PasswordInfo{
{ {
UserID: "ID-1", UserID: "ID-1",
Password: []byte("password-1"), Password: []byte("password-1"),
@ -133,6 +134,12 @@ func makeTestFixtures() (*UsersAPI, *testEmailer) {
Password: []byte("password-2"), Password: []byte("password-2"),
}, },
}) })
if err != nil {
panic("Failed to create user repo: " + err.Error())
}
return repo
}()
ccr := connector.NewConnectorConfigRepoFromConfigs([]connector.ConnectorConfig{ ccr := connector.NewConnectorConfigRepoFromConfigs([]connector.ConnectorConfig{
&connector.LocalConnectorConfig{ID: "local"}, &connector.LocalConnectorConfig{ID: "local"},
}) })

View file

@ -46,8 +46,9 @@ func (t *testEmailer) SendMail(from, subject, text, html string, to ...string) e
} }
func makeTestFixtures() (*UserEmailer, *testEmailer, *key.PublicKey) { func makeTestFixtures() (*UserEmailer, *testEmailer, *key.PublicKey) {
dbMap := db.NewMemDB()
ur := func() user.UserRepo { ur := func() user.UserRepo {
repo, err := db.NewUserRepoFromUsers(db.NewMemDB(), []user.UserWithRemoteIdentities{ repo, err := db.NewUserRepoFromUsers(dbMap, []user.UserWithRemoteIdentities{
{ {
User: user.User{ User: user.User{
ID: "ID-1", ID: "ID-1",
@ -72,7 +73,8 @@ func makeTestFixtures() (*UserEmailer, *testEmailer, *key.PublicKey) {
return repo return repo
}() }()
pwr := user.NewPasswordInfoRepoFromPasswordInfos([]user.PasswordInfo{ pwr := func() user.PasswordInfoRepo {
repo, err := db.NewPasswordInfoRepoFromPasswordInfos(dbMap, []user.PasswordInfo{
{ {
UserID: "ID-1", UserID: "ID-1",
Password: []byte("password-1"), Password: []byte("password-1"),
@ -82,6 +84,11 @@ func makeTestFixtures() (*UserEmailer, *testEmailer, *key.PublicKey) {
Password: []byte("password-2"), Password: []byte("password-2"),
}, },
}) })
if err != nil {
panic("Failed to create user repo: " + err.Error())
}
return repo
}()
privKey, err := key.GeneratePrivateKey() privKey, err := key.GeneratePrivateKey()
if err != nil { if err != nil {

View file

@ -60,7 +60,8 @@ func makeTestFixtures() *testFixtures {
return repo return repo
}() }()
f.pwr = user.NewPasswordInfoRepoFromPasswordInfos([]user.PasswordInfo{ f.pwr = func() user.PasswordInfoRepo {
repo, err := db.NewPasswordInfoRepoFromPasswordInfos(dbMap, []user.PasswordInfo{
{ {
UserID: "ID-1", UserID: "ID-1",
Password: []byte("password-1"), Password: []byte("password-1"),
@ -70,6 +71,12 @@ func makeTestFixtures() *testFixtures {
Password: []byte("password-2"), Password: []byte("password-2"),
}, },
}) })
if err != nil {
panic("Failed to create user repo: " + err.Error())
}
return repo
}()
f.ccr = connector.NewConnectorConfigRepoFromConfigs([]connector.ConnectorConfig{ f.ccr = connector.NewConnectorConfigRepoFromConfigs([]connector.ConnectorConfig{
&connector.LocalConnectorConfig{ID: "local"}, &connector.LocalConnectorConfig{ID: "local"},
}) })
@ -215,18 +222,22 @@ func TestRegisterWithPassword(t *testing.T) {
} }
if diff := pretty.Compare(usr, ridUSR); diff != "" { if diff := pretty.Compare(usr, ridUSR); diff != "" {
t.Errorf("case %d: Compare(want, got) = %v", i, diff) t.Errorf("case %d: Compare(want, got) = %v", i, diff)
continue
} }
pwi, err := f.pwr.Get(nil, userID) pwi, err := f.pwr.Get(nil, userID)
if err != nil { if err != nil {
t.Errorf("case %d: err != nil: %q", i, err) t.Errorf("case %d: err != nil: %q", i, err)
continue
} }
ident, err := pwi.Authenticate(tt.plaintext) ident, err := pwi.Authenticate(tt.plaintext)
if err != nil { if err != nil {
t.Errorf("case %d: err != nil: %q", i, err) t.Errorf("case %d: err != nil: %q", i, err)
continue
} }
if ident.ID != userID { if ident.ID != userID {
t.Errorf("case %d: ident.ID: want=%q, got=%q", i, userID, ident.ID) t.Errorf("case %d: ident.ID: want=%q, got=%q", i, userID, ident.ID)
continue
} }
_, err = pwi.Authenticate(tt.plaintext + "WRONG") _, err = pwi.Authenticate(tt.plaintext + "WRONG")

View file

@ -4,9 +4,7 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io"
"net/url" "net/url"
"os"
"time" "time"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
@ -85,60 +83,6 @@ type PasswordInfoRepo interface {
Create(repo.Transaction, PasswordInfo) error Create(repo.Transaction, PasswordInfo) error
} }
func NewPasswordInfoRepo() PasswordInfoRepo {
return &memPasswordInfoRepo{
pws: make(map[string]PasswordInfo),
}
}
type memPasswordInfoRepo struct {
pws map[string]PasswordInfo
}
func (m *memPasswordInfoRepo) Get(_ repo.Transaction, id string) (PasswordInfo, error) {
pw, ok := m.pws[id]
if !ok {
return PasswordInfo{}, ErrorNotFound
}
return pw, nil
}
func (m *memPasswordInfoRepo) Create(_ repo.Transaction, pw PasswordInfo) error {
_, ok := m.pws[pw.UserID]
if ok {
return ErrorDuplicateID
}
if pw.UserID == "" {
return ErrorInvalidID
}
if len(pw.Password) == 0 {
return ErrorInvalidPassword
}
m.pws[pw.UserID] = pw
return nil
}
func (m *memPasswordInfoRepo) Update(_ repo.Transaction, pw PasswordInfo) error {
if pw.UserID == "" {
return ErrorInvalidID
}
_, ok := m.pws[pw.UserID]
if !ok {
return ErrorNotFound
}
if len(pw.Password) == 0 {
return ErrorInvalidPassword
}
m.pws[pw.UserID] = pw
return nil
}
func (u *PasswordInfo) UnmarshalJSON(data []byte) error { func (u *PasswordInfo) UnmarshalJSON(data []byte) error {
var dec struct { var dec struct {
UserID string `json:"userId"` UserID string `json:"userId"`
@ -172,21 +116,6 @@ func (u *PasswordInfo) UnmarshalJSON(data []byte) error {
return nil return nil
} }
func newPasswordInfosFromReader(r io.Reader) ([]PasswordInfo, error) {
var pws []PasswordInfo
err := json.NewDecoder(r).Decode(&pws)
return pws, err
}
func readPasswordInfosFromFile(loc string) ([]PasswordInfo, error) {
pwf, err := os.Open(loc)
if err != nil {
return nil, fmt.Errorf("unable to read password info from file %q: %v", loc, err)
}
return newPasswordInfosFromReader(pwf)
}
func LoadPasswordInfos(repo PasswordInfoRepo, pws []PasswordInfo) error { func LoadPasswordInfos(repo PasswordInfoRepo, pws []PasswordInfo) error {
for i, pw := range pws { for i, pw := range pws {
err := repo.Create(nil, pw) err := repo.Create(nil, pw)
@ -197,23 +126,6 @@ func LoadPasswordInfos(repo PasswordInfoRepo, pws []PasswordInfo) error {
return nil return nil
} }
func NewPasswordInfoRepoFromPasswordInfos(pws []PasswordInfo) PasswordInfoRepo {
memRepo := NewPasswordInfoRepo().(*memPasswordInfoRepo)
for _, pw := range pws {
memRepo.pws[pw.UserID] = pw
}
return memRepo
}
func NewPasswordInfoRepoFromFile(loc string) (PasswordInfoRepo, error) {
pws, err := readPasswordInfosFromFile(loc)
if err != nil {
return nil, err
}
return NewPasswordInfoRepoFromPasswordInfos(pws), nil
}
func NewPasswordReset(userID string, password Password, issuer url.URL, clientID string, callback url.URL, expires time.Duration) PasswordReset { func NewPasswordReset(userID string, password Password, issuer url.URL, clientID string, callback url.URL, expires time.Duration) PasswordReset {
claims := oidc.NewClaims(issuer.String(), userID, clientID, clock.Now(), clock.Now().Add(expires)) claims := oidc.NewClaims(issuer.String(), userID, clientID, clock.Now(), clock.Now().Add(expires))
claims.Add(ClaimPasswordResetPassword, string(password)) claims.Add(ClaimPasswordResetPassword, string(password))

View file

@ -2,7 +2,6 @@ package user
import ( import (
"net/url" "net/url"
"strings"
"testing" "testing"
"time" "time"
@ -14,48 +13,6 @@ import (
"github.com/coreos/go-oidc/key" "github.com/coreos/go-oidc/key"
) )
func TestNewPasswordInfosFromReader(t *testing.T) {
PasswordHasher = func(plaintext string) ([]byte, error) {
return []byte(strings.ToUpper(plaintext)), nil
}
defer func() {
PasswordHasher = DefaultPasswordHasher
}()
tests := []struct {
json string
want []PasswordInfo
}{
{
json: `[{"userId":"12345","passwordPlaintext":"password"},{"userId":"78901","passwordHash":"WORDPASS", "passwordExpires":"2006-01-01T15:04:05Z"}]`,
want: []PasswordInfo{
{
UserID: "12345",
Password: []byte("PASSWORD"),
},
{
UserID: "78901",
Password: []byte("WORDPASS"),
PasswordExpires: time.Date(2006,
1, 1, 15, 4, 5, 0, time.UTC),
},
},
},
}
for i, tt := range tests {
r := strings.NewReader(tt.json)
us, err := newPasswordInfosFromReader(r)
if err != nil {
t.Errorf("case %d: want nil err: %v", i, err)
continue
}
if diff := pretty.Compare(tt.want, us); diff != "" {
t.Errorf("case %d: Compare(want, got): %v", i, diff)
}
}
}
func TestNewPasswordFromHash(t *testing.T) { func TestNewPasswordFromHash(t *testing.T) {
tests := []string{ tests := []string{
"test", "test",