forked from mystiq/dex
*: remove in memory password info repo
This commit is contained in:
parent
2726f4dcdf
commit
72d1ecab64
13 changed files with 100 additions and 177 deletions
|
@ -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"},
|
||||||
})
|
})
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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"}},
|
||||||
|
|
|
@ -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{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
@ -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
2
test
|
@ -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
|
||||||
|
|
|
@ -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"},
|
||||||
})
|
})
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Reference in a new issue