Skip to content
Snippets Groups Projects
Commit 296c3ec1 authored by ale's avatar ale
Browse files

Merge branch 'dovecot-singleflight' into 'master'

Do not have more than one passdb request in-flight for a user

See merge request !34
parents 013b5ffb f0bbb02a
No related branches found
No related tags found
1 merge request!34Do not have more than one passdb request in-flight for a user
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
"git.autistici.org/ai3/go-common/clientutil" "git.autistici.org/ai3/go-common/clientutil"
"git.autistici.org/ai3/go-common/userenckey" "git.autistici.org/ai3/go-common/userenckey"
"golang.org/x/sync/singleflight"
"git.autistici.org/id/keystore/backend" "git.autistici.org/id/keystore/backend"
ldapBE "git.autistici.org/id/keystore/backend/ldap" ldapBE "git.autistici.org/id/keystore/backend/ldap"
...@@ -82,6 +83,7 @@ var passwordSep = "/" ...@@ -82,6 +83,7 @@ var passwordSep = "/"
type KeyLookupProxy struct { type KeyLookupProxy struct {
config *Config config *Config
keystore client.Client keystore client.Client
sfgroup singleflight.Group
db backend.Database db backend.Database
} }
...@@ -151,7 +153,29 @@ func (s *KeyLookupProxy) lookupUserdb(ctx context.Context, username string) (int ...@@ -151,7 +153,29 @@ func (s *KeyLookupProxy) lookupUserdb(ctx context.Context, username string) (int
return newUserDBResponse(s.b64encode(pub)), true, nil return newUserDBResponse(s.b64encode(pub)), true, nil
} }
type passdbLookupResult struct {
obj interface{}
ok bool
}
func (s *KeyLookupProxy) lookupPassdb(ctx context.Context, username, password string) (interface{}, bool, error) { func (s *KeyLookupProxy) lookupPassdb(ctx context.Context, username, password string) (interface{}, bool, error) {
// In order to wrap lookupPassdb() in a singleflight group we wrap its
// return parameters in a struct, with some additional error handling.
res, err, _ := s.sfgroup.Do(username, func() (interface{}, error) {
obj, ok, err := s.lookupPassdbReal(ctx, username, password)
if err != nil {
return nil, err
}
return &passdbLookupResult{obj: obj, ok: ok}, nil
})
if err != nil {
return nil, false, err
}
plr := res.(*passdbLookupResult)
return plr.obj, plr.ok, nil
}
func (s *KeyLookupProxy) lookupPassdbReal(ctx context.Context, username, password string) (interface{}, bool, error) {
// The password might be a SSO token, so first of all we try // The password might be a SSO token, so first of all we try
// to fetch the unencrypted key from the keystore daemon. // to fetch the unencrypted key from the keystore daemon.
var keystoreStatus string var keystoreStatus string
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment